peuler 0.1.0

A Rust crate with solutions to the Project Euler problems
Documentation
use crate::Solution;

problem!(Problem0089, 89, "Roman Numerals");

impl Solution for Problem0089 {
    fn solve(&self) -> String {
        const INPUT: &str = include_str!("0089_roman.txt");
        let mut saved_chars = 0;

        for roman_numeral in INPUT.lines() {
            saved_chars += roman_numeral.chars().count();
            saved_chars -= int_2_roman(roman_2_int(roman_numeral)).chars().count();
        }

        saved_chars.to_string()
    }
}

fn int_2_roman(mut num: u16) -> String {
    let mut roman = String::with_capacity(4);

    for _ in 0..num / 1000 {
        roman.push('M');
    }
    num %= 1000;

    let hundreds = num / 100;
    num %= 100;
    match hundreds {
        9 => roman.push_str("CM"),
        5..=8 => {
            roman.push('D');
            (5..hundreds).for_each(|_| roman.push('C'));
        }
        4 => roman.push_str("CD"),
        _ => (0..hundreds).for_each(|_| roman.push('C')),
    }

    let tens = num / 10;
    num %= 10;
    match tens {
        9 => roman.push_str("XC"),
        5..=8 => {
            roman.push('L');
            (5..tens).for_each(|_| roman.push('X'));
        }
        4 => roman.push_str("XL"),
        _ => (0..tens).for_each(|_| roman.push('X')),
    }

    match num {
        9 => roman.push_str("IX"),
        5..=8 => {
            roman.push('V');
            (5..num).for_each(|_| roman.push('I'));
        }
        4 => roman.push_str("IV"),
        _ => (0..num).for_each(|_| roman.push('I')),
    }

    roman
}

fn roman_2_int(roman: &str) -> u16 {
    let mut integer = 0;

    let mut iter = roman.chars().peekable();
    while let Some(c) = iter.next() {
        match c {
            'I' => match iter.peek() {
                Some('V') => {
                    integer += 4;
                    iter.next();
                }
                Some('X') => {
                    integer += 9;
                    iter.next();
                }
                _ => integer += 1,
            },
            'V' => integer += 5,
            'X' => match iter.peek() {
                Some('L') => {
                    integer += 40;
                    iter.next();
                }
                Some('C') => {
                    integer += 90;
                    iter.next();
                }
                _ => integer += 10,
            },
            'L' => integer += 50,
            'C' => match iter.peek() {
                Some('D') => {
                    integer += 400;
                    iter.next();
                }
                Some('M') => {
                    integer += 900;
                    iter.next();
                }
                _ => integer += 100,
            },
            'D' => integer += 500,
            'M' => integer += 1000,
            _ => (),
        }
    }

    integer
}