diff --git a/src/bin/d25p1.rs b/src/bin/d25p1.rs new file mode 100644 index 0000000..f2435f1 --- /dev/null +++ b/src/bin/d25p1.rs @@ -0,0 +1,8 @@ +use aoc22::{day25, util}; + +pub fn main() { + let numbers = day25::parse_snafus(&util::parse_input()); + let sum: i64 = numbers.iter().sum(); + println!("Sum of numbers: {}", sum); + println!("Sum of numbers, SNAFU'd: {}", day25::num_to_snafu(sum)); +} diff --git a/src/day25.rs b/src/day25.rs new file mode 100644 index 0000000..c9d2efe --- /dev/null +++ b/src/day25.rs @@ -0,0 +1,83 @@ +use std::collections::VecDeque; + +pub fn parse_snafus(input: &str) -> Vec { + input.lines().map(snafu_to_num).collect() +} + +pub fn snafu_to_num(snafu: &str) -> i64 { + let mut pow = 1; + let mut result = 0; + for c in snafu.chars().rev() { + let digit = match c { + '=' => -2, + '-' => -1, + '0' => 0, + '1' => 1, + '2' => 2, + _ => panic!("Unknown digit {}", c), + }; + result += pow * digit; + pow *= 5; + } + result +} + +pub fn num_to_snafu(num: i64) -> String { + assert!(num > 0); + + let exp = (num as f64).log(5.0).floor() as u32 + 1; + let mut result = VecDeque::with_capacity((exp as usize) + 1); + let mut pow = 5_i64.pow(exp); + let mut rem = num; + + while pow >= 1 { + let digit = rem / pow; + rem %= pow; + result.push_back(digit); + pow /= 5; + } + + for i in (0..result.len()).rev() { + if result[i] > 2 { + result[i] -= 5; + result[i - 1] += 1; + } + } + + result + .iter() + .skip_while(|d| **d == 0) + .map(|d| match d { + -2 => '=', + -1 => '-', + 0 => '0', + 1 => '1', + 2 => '2', + _ => panic!("Unknown digit {}", d), + }) + .collect() +} + +#[cfg(test)] +mod tests { + #[test] + fn num_to_snafu_examples() { + use crate::day25::num_to_snafu; + assert_eq!(num_to_snafu(1), "1"); + assert_eq!(num_to_snafu(2), "2"); + assert_eq!(num_to_snafu(3), "1="); + assert_eq!(num_to_snafu(4), "1-"); + assert_eq!(num_to_snafu(5), "10"); + assert_eq!(num_to_snafu(6), "11"); + assert_eq!(num_to_snafu(7), "12"); + assert_eq!(num_to_snafu(8), "2="); + assert_eq!(num_to_snafu(9), "2-"); + assert_eq!(num_to_snafu(10), "20"); + assert_eq!(num_to_snafu(15), "1=0"); + assert_eq!(num_to_snafu(20), "1-0"); + assert_eq!(num_to_snafu(2022), "1=11-2"); + assert_eq!(num_to_snafu(12345), "1-0---0"); + assert_eq!(num_to_snafu(314159265), "1121-1110-1=0"); + assert_eq!(num_to_snafu(4890), "2=-1=0"); + } +} diff --git a/src/lib.rs b/src/lib.rs index 5e356e7..3b926e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ pub mod day21; pub mod day22; pub mod day23; pub mod day24; +pub mod day25; pub mod day3; pub mod day4; pub mod day5;