diff options
| author | Josh Kingsley <josh@joshkingsley.me> | 2025-12-02 06:42:49 +0200 |
|---|---|---|
| committer | Josh Kingsley <josh@joshkingsley.me> | 2025-12-02 06:42:49 +0200 |
| commit | a92145d53d761dc54b34851ebb410a43efb2cfbc (patch) | |
| tree | 99ebd2da54400ecb06401335af282a60c9795117 /day1 | |
| parent | 7f5b7771e2725f32d4a6aea4a50ddc46c474a14b (diff) | |
Day 1, part 2 working with example
Diffstat (limited to 'day1')
| -rw-r--r-- | day1/src/main.rs | 153 |
1 files changed, 132 insertions, 21 deletions
diff --git a/day1/src/main.rs b/day1/src/main.rs index 5931c59..2058021 100644 --- a/day1/src/main.rs +++ b/day1/src/main.rs @@ -33,13 +33,64 @@ impl FromStr for Rotation { } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] struct Dial(u8); +struct RotateResult(u32, Dial); + impl Dial { fn new() -> Self { Self(50) } + + fn rotate(self, rot: &Rotation) -> RotateResult { + match rot { + Rotation::Left(n) => self.rotate_left(*n), + Rotation::Right(n) => self.rotate_right(*n), + } + } + + fn rotate_left(self, n: u32) -> RotateResult { + let pos = self.0 as u32; + + if pos != 0 && n >= pos { + let quot = n.div_ceil(100); + RotateResult(quot, self - n) + } else { + RotateResult(0, self - n) + } + } + + fn rotate_right(self, n: u32) -> RotateResult { + let pos = self.0 as u32; + + if n + pos >= 100 { + let quot = n.div_ceil(100); + RotateResult(quot, self + n) + } else { + RotateResult(0, self + n) + } + } + + fn rotate_all(self, rotations: &[Rotation]) -> RotateResult { + let mut dial = Dial::from(50); + let mut zeros_total = 0; + + for rot in rotations { + let RotateResult(zeros, new_dial) = dial.rotate(rot); + zeros_total += zeros; + dial = new_dial; + println!("{:?}, dial: {}, zeros: {}", rot, dial.0, zeros); + } + + RotateResult(zeros_total, dial) + } +} + +impl From<u8> for Dial { + fn from(value: u8) -> Self { + Self(value) + } } impl Add<u32> for Dial { @@ -68,28 +119,14 @@ impl PartialEq<u8> for Dial { } } -fn main() -> anyhow::Result<()> { - let mut args = env::args(); - let input_path = args.nth(1).ok_or(anyhow!("usage: day1 INPUT"))?; - let input = fs::read_to_string(input_path)?; - - let rotations: Vec<Rotation> = input - .split_whitespace() - .map(|s| s.parse().map_err(|_| anyhow!("bad rotation: {}", s))) - .collect::<anyhow::Result<_>>()?; - - println!("rotations: {}", rotations.len()); - +fn part1(rotations: &[Rotation]) -> RotateResult { let mut dial = Dial::new(); let mut zeros = 0; for rot in rotations { - println!("dial: {}", dial.0); - println!("rotation: {:?}", rot); - match rot { - Rotation::Left(n) => dial = dial - n, - Rotation::Right(n) => dial = dial + n, + Rotation::Left(n) => dial = dial - *n, + Rotation::Right(n) => dial = dial + *n, } if dial == 0 { @@ -97,9 +134,45 @@ fn main() -> anyhow::Result<()> { } } - println!("zeros: {}", zeros); + RotateResult(zeros, dial) +} + +fn main() -> anyhow::Result<()> { + let usage_err = || anyhow!("usage: day1 PART INPUT"); + + let mut args = env::args(); + + let part: u8 = args + .nth(1) + .ok_or_else(usage_err)? + .parse() + .map_err(|_| usage_err())?; + + let input_path = args.next().ok_or_else(usage_err)?; + + let input = fs::read_to_string(input_path)?; + + let rotations: Vec<Rotation> = input + .split_whitespace() + .map(|s| s.parse().map_err(|_| anyhow!("bad rotation: {}", s))) + .collect::<anyhow::Result<_>>()?; + + match part { + 1 => { + let RotateResult(zeros, _) = part1(&rotations); + println!("Result: {}", zeros); + Ok(()) + } + + 2 => { + let dial = Dial::from(50); + let RotateResult(zeros, _) = dial.rotate_all(&rotations); + println!("Result: {}", zeros); + Ok(()) + } - Ok(()) + _ => Err(usage_err()), + } } #[cfg(test)] @@ -122,7 +195,7 @@ mod tests { } #[test] - fn dial() { + fn dial_ops() { let dial = Dial::new(); assert_eq!(dial + 1, 51); @@ -143,4 +216,42 @@ mod tests { assert_eq!(dial - 51, 99); assert_eq!(dial - 50, 0); } + + #[test] + fn dial_rotate() { + let mut dial = Dial::new(); + + let rotations = vec![ + // Example data + (Rotation::Left(68), 1, 82), + (Rotation::Left(30), 0, 52), + (Rotation::Right(48), 1, 0), + (Rotation::Left(5), 0, 95), + (Rotation::Right(60), 1, 55), + (Rotation::Left(55), 1, 0), + (Rotation::Left(1), 0, 99), + (Rotation::Left(99), 1, 0), + (Rotation::Right(14), 0, 14), + (Rotation::Left(82), 1, 32), + // Additional data + (Rotation::Left(200), 2, 32), + (Rotation::Right(200), 2, 32), + (Rotation::Left(30), 0, 2), + (Rotation::Left(10), 1, 92), + (Rotation::Right(10), 1, 2), + (Rotation::Left(110), 2, 92), + (Rotation::Right(210), 3, 2), + (Rotation::Right(48), 0, 50), + (Rotation::Right(1000), 10, 50), + (Rotation::Right(48), 0, 98), + (Rotation::Left(651), 6, 47), + ]; + + for (rot, expected_zeros, expected_dial) in &rotations { + let RotateResult(zeros, new_dial) = dial.rotate(rot); + assert_eq!(&zeros, expected_zeros, "rotating with {:?}", rot); + assert_eq!(&new_dial, expected_dial, "rotating with {:?}", rot); + dial = new_dial; + } + } } |
