aboutsummaryrefslogtreecommitdiff
path: root/day1
diff options
context:
space:
mode:
Diffstat (limited to 'day1')
-rw-r--r--day1/src/main.rs153
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;
+ }
+ }
}