day25.rs (1902B)
1 fn from_snafu(s: &str) -> i64 { 2 // This is the easy bit... 3 let mut i: i64 = 0; 4 let mut pow: i64 = 1; 5 for ch in s.chars().rev() { 6 match ch { 7 '2' => i += 2 * pow, 8 '1' => i += 1 * pow, 9 '0' => {}, // additive identity! 10 '-' => i += -1 * pow, 11 '=' => i += -2 * pow, 12 _ => panic!("unexpected input {}", ch) 13 } 14 pow *= 5; 15 } 16 i 17 } 18 19 fn to_snafu(mut i: i64) -> String { 20 // how to do this :thinking: add two, mod 5,take away 2? // nope 21 let mut res = Vec::<char>::new(); 22 while i != 0 { 23 let d = ((i + 2) % 5) - 2; 24 let ch = match d { 25 2 => '2', 26 1 => '1', 27 0 => '0', 28 -1 => '-', 29 -2 => '=', 30 _ => panic!("unexpected digit {}", d) 31 }; 32 res.push(ch); 33 i = (i + 2) / 5; 34 } 35 res.reverse(); 36 res.into_iter().collect::<String>() 37 } 38 39 #[cfg(test)] 40 mod tests { 41 use super::*; 42 #[test] 43 fn test_from_snafu() { 44 let cases = vec![ 45 ("1=-0-2", "1747"), 46 ( "12111", "906"), 47 ( "2=0=", "198"), 48 ( "21", "11"), // works 49 ( "2=01", "201"), // 201,1 > 40,0 > 8,= > 1,1 50 ( "111", "31"), // works 51 ( "20012", "1257"), //works 52 ( "112", "32"), // works 53 ( "1=-1=", "353"), // broke 54 ( "1-12", "107"), 55 ( "12", "7"), 56 ( "1=", "3"), 57 ( "122", "37"), 58 ]; 59 for (snafu, decimal) in cases { 60 let x = from_snafu(snafu); 61 assert_eq!(x.to_string().as_str(), decimal); 62 assert_eq!(to_snafu(x), snafu); 63 } 64 } 65 } 66 67 pub fn run(input: String) { 68 let s: i64 = input.lines() 69 .map(from_snafu) 70 .sum(); 71 println!("Day 25: {}", to_snafu(s)); 72 }