fn from_snafu(s: &str) -> i64 { // This is the easy bit... let mut i: i64 = 0; let mut pow: i64 = 1; for ch in s.chars().rev() { match ch { '2' => i += 2 * pow, '1' => i += 1 * pow, '0' => {}, // additive identity! '-' => i += -1 * pow, '=' => i += -2 * pow, _ => panic!("unexpected input {}", ch) } pow *= 5; } i } fn to_snafu(mut i: i64) -> String { // how to do this :thinking: add two, mod 5,take away 2? // nope let mut res = Vec::::new(); while i != 0 { let d = ((i + 2) % 5) - 2; let ch = match d { 2 => '2', 1 => '1', 0 => '0', -1 => '-', -2 => '=', _ => panic!("unexpected digit {}", d) }; res.push(ch); i = (i + 2) / 5; } res.reverse(); res.into_iter().collect::() } #[cfg(test)] mod tests { use super::*; #[test] fn test_from_snafu() { let cases = vec![ ("1=-0-2", "1747"), ( "12111", "906"), ( "2=0=", "198"), ( "21", "11"), // works ( "2=01", "201"), // 201,1 > 40,0 > 8,= > 1,1 ( "111", "31"), // works ( "20012", "1257"), //works ( "112", "32"), // works ( "1=-1=", "353"), // broke ( "1-12", "107"), ( "12", "7"), ( "1=", "3"), ( "122", "37"), ]; for (snafu, decimal) in cases { let x = from_snafu(snafu); assert_eq!(x.to_string().as_str(), decimal); assert_eq!(to_snafu(x), snafu); } } } pub fn run(input: String) { let s: i64 = input.lines() .map(from_snafu) .sum(); println!("Day 25: {}", to_snafu(s)); }