diff --git a/projecteuler/089/src/main.rs b/projecteuler/089/src/main.rs index cdff4d5..428a892 100644 --- a/projecteuler/089/src/main.rs +++ b/projecteuler/089/src/main.rs @@ -20,7 +20,23 @@ enum RomanNum { use RomanNum::*; type RomanNumeral = Vec; +impl RomanNum { + fn to_digit(&self) -> u32 { + match self { + I => 1, + V => 5, + X => 10, + L => 50, + C => 100, + D => 500, + M => 1000, + Empty => 0, + } + } +} + // This function is not correct at all but I'm not gonna bother fixing it +#[deprecated] fn _is_minimal(number: &RomanNumeral) -> bool { let mut last_num = Empty; let mut occ = 0; @@ -43,7 +59,8 @@ fn _is_minimal(number: &RomanNumeral) -> bool { true } -fn reduce(original: &RomanNumeral) -> RomanNumeral { +#[deprecated] +fn _reduce(original: &RomanNumeral) -> RomanNumeral { let mut last_num = Empty; let mut occ = 0; let mut result = vec![]; @@ -167,7 +184,8 @@ fn reduce(original: &RomanNumeral) -> RomanNumeral { result } -fn reduce_extra(numeral: &RomanNumeral) -> RomanNumeral { +#[deprecated] +fn _reduce_extra(numeral: &RomanNumeral) -> RomanNumeral { if numeral.len() <= 3 { return numeral.clone(); } @@ -211,6 +229,106 @@ fn reduce_extra(numeral: &RomanNumeral) -> RomanNumeral { result.into_iter().filter(|&n| n != Empty).collect() } +fn roman_to_decimal(number: &RomanNumeral) -> u32 { + let mut result: i32 = 0; + let mut last; + let mut current = Empty; + + for &num in number.iter() { + last = current; + current = num; + + if last.to_digit() < current.to_digit() { + result -= last.to_digit() as i32; + } else { + result += last.to_digit() as i32; + } + } + + result += current.to_digit() as i32; + result as u32 +} + +fn decimal_to_roman(number: u32) -> RomanNumeral { + let mut n = number; + let mut result = vec![]; + + while n > 0 { + while n >= 1000 { + result.push(M); + n -= 1000; + } + + if n >= 900 { + result.push(C); + result.push(M); + n -= 900; + } + + if n >= 500 { + result.push(D); + n -= 500; + } + + if n >= 400 { + result.push(C); + result.push(D); + n -= 400; + } + + while n >= 100 { + result.push(C); + n -= 100; + } + + if n >= 90 { + result.push(X); + result.push(C); + n -= 90; + } + + if n >= 50 { + result.push(L); + n -= 50; + } + + if n >= 40 { + result.push(X); + result.push(L); + n -= 40; + } + + while n >= 10 { + result.push(X); + n -= 10; + } + + if n == 9 { + result.push(I); + result.push(X); + n -= 9; + } + + if n >= 5 { + result.push(V); + n -= 5; + } + + if n == 4 { + result.push(I); + result.push(V); + n -= 4; + } + + while n > 0 { + result.push(I); + n -= 1; + } + } + + result +} + fn parse_input(input: &str) -> IResult<&str, Vec> { let (input, result) = separated_list1( multispace1, @@ -250,21 +368,37 @@ fn main() { // println!("{:?}", res); let (_, numerals) = parse_input(input_text).unwrap(); - let mut result = 0; - for mut numeral in numerals { - let start = numeral.len(); - let mut s = start; - loop { - numeral = reduce(&numeral); - numeral = reduce_extra(&numeral); - if s == numeral.len() { - break; - } - s = numeral.len(); - } - result += start - numeral.len(); - println!("{:?} , {}", numeral, start - numeral.len()); + + // for mut numeral in numerals { + // let start = numeral.len(); + // let mut s = start; + // loop { + // numeral = reduce(&numeral); + // numeral = reduce_extra(&numeral); + // if s == numeral.len() { + // break; + // } + // s = numeral.len(); + // } + // result += start - numeral.len(); + // println!("{:?} , {}", numeral, start - numeral.len()); + // } + + // Thanks chat gpt for giving me the direction of a solution that should work (although let the record state that the specific solution it generated was not correct at all) + for numeral in numerals { + let l = numeral.len(); + let dec_version = roman_to_decimal(&numeral); + let rom_version = decimal_to_roman(dec_version); + + // println!( + // "{:?} calculated to be {} then represented as {:?}", + // numeral, &dec_version, &rom_version, + // ); + + debug_assert!(l >= rom_version.len()); + + result += l - rom_version.len(); } println!("The number of characters that can be saved is: {}", result);