From 3a419be8836ae6e51adc20ba484b6c091ce696ec Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 25 Dec 2022 14:08:37 +0200 Subject: Day 25 --- 2022/src/bin/day_25.rs | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 2022/src/bin/day_25.rs (limited to '2022/src/bin') diff --git a/2022/src/bin/day_25.rs b/2022/src/bin/day_25.rs new file mode 100644 index 0000000..d55f30a --- /dev/null +++ b/2022/src/bin/day_25.rs @@ -0,0 +1,111 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::line_ending, + combinator::{map, value}, + multi::{many1, separated_list1}, + IResult, +}; +use std::fs; + +fn main() -> Result<(), Box> { + let input = fs::read_to_string("inputs/day_25.txt")?; + let parsed = SnafuList::parser(&input).unwrap().1; + dbg!(to_snafu(parsed.sum())); + + Ok(()) +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct SnafuList(Vec); + +impl SnafuList { + fn parser(input: &str) -> IResult<&str, SnafuList> { + map( + separated_list1( + line_ending, + map( + many1(alt(( + value(2, tag("2")), + value(1, tag("1")), + value(0, tag("0")), + value(-1, tag("-")), + value(-2, tag("=")), + ))), + |digits| { + let mut result: i64 = 0; + for digit in digits { + result *= 5; + result += digit; + } + result + }, + ), + ), + SnafuList, + )(input) + } + + fn sum(&self) -> i64 { + self.0.iter().sum() + } +} + +fn to_snafu(mut remaining_value: i64) -> String { + let mut result = String::new(); + + let mut current_power = 5i64.pow(26); + + while current_power > 0 { + let next_digit_range = { + let mut next_digit_power = current_power / 5; + let mut max_next_digit = 0; + while next_digit_power > 0 { + max_next_digit += 2 * next_digit_power; + next_digit_power /= 5; + } + -max_next_digit..=max_next_digit + }; + + let (digit, digit_value) = [('=', -2), ('-', -1), ('0', 0), ('1', 1), ('2', 2)] + .into_iter() + .filter_map(|(digit, digit_value)| { + let digit_value = digit_value * current_power; + let remaining_if_digit_set = remaining_value - digit_value; + if next_digit_range.contains(&remaining_if_digit_set) { + Some((digit, digit_value)) + } else { + None + } + }) + .next() + .expect("No digit found"); + + remaining_value -= digit_value; + result.push(digit); + + current_power /= 5; + } + + result.trim_start_matches("0").to_owned() +} + +#[test] +fn round_trip_works() { + let str_list = vec![ + "1=-0-2", "12111", "2=0=", "21", "2=01", "111", "20012", "112", "1=-1=", "1-12", "12", + "1=", "122", + ]; + let list = SnafuList::parser(&str_list.join("\n")).unwrap().1; + + assert_eq!( + list, + SnafuList(vec![ + 1747, 906, 198, 11, 201, 31, 1257, 32, 353, 107, 7, 3, 37 + ]) + ); + + for (i, num) in list.0.iter().enumerate() { + assert_eq!(to_snafu(*num), str_list[i]); + } +} -- cgit v1.2.3