diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0ba3ea5..8ddebbd 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -59,6 +59,10 @@ path = "src/day08/main.rs" name = "day09" path = "src/day09/main.rs" +[[bin]] +name = "day10" +path = "src/day10/main.rs" + [dependencies] # Required for one of the day06 solutions (commented out) # phf = { version = "0.11.1", features = ["macros"] } \ No newline at end of file diff --git a/rust/src/day10/input.txt b/rust/src/day10/input.txt new file mode 100644 index 0000000..dfbe1fa --- /dev/null +++ b/rust/src/day10/input.txt @@ -0,0 +1,137 @@ +noop +addx 7 +addx -1 +addx -1 +addx 5 +noop +noop +addx 1 +addx 3 +addx 2 +noop +addx 2 +addx 5 +addx 2 +addx 10 +addx -9 +addx 4 +noop +noop +noop +addx 3 +addx 5 +addx -40 +addx 26 +addx -23 +addx 2 +addx 5 +addx 26 +addx -35 +addx 12 +addx 2 +addx 17 +addx -10 +addx 3 +noop +addx 2 +addx 3 +noop +addx 2 +addx 3 +noop +addx 2 +addx 2 +addx -39 +noop +addx 15 +addx -12 +addx 2 +addx 10 +noop +addx -1 +addx -2 +noop +addx 5 +noop +addx 5 +noop +noop +addx 1 +addx 4 +addx -25 +addx 26 +addx 2 +addx 5 +addx 2 +noop +addx -3 +addx -32 +addx 1 +addx 4 +addx -2 +addx 3 +noop +noop +addx 3 +noop +addx 6 +addx -17 +addx 27 +addx -7 +addx 5 +addx 2 +addx 3 +addx -2 +addx 4 +noop +noop +addx 5 +addx 2 +addx -39 +noop +noop +addx 2 +addx 5 +addx 3 +addx -2 +addx 2 +addx 11 +addx -4 +addx -5 +noop +addx 10 +addx -18 +addx 19 +addx 2 +addx 5 +addx 2 +addx 2 +addx 3 +addx -2 +addx 2 +addx -37 +noop +addx 5 +addx 4 +addx -1 +noop +addx 4 +noop +noop +addx 1 +addx 4 +noop +addx 1 +addx 2 +noop +addx 3 +addx 5 +noop +addx -3 +addx 5 +addx 5 +addx 2 +addx 3 +noop +addx -32 +noop \ No newline at end of file diff --git a/rust/src/day10/main.rs b/rust/src/day10/main.rs new file mode 100644 index 0000000..1c0e226 --- /dev/null +++ b/rust/src/day10/main.rs @@ -0,0 +1,56 @@ +const INPUT: &str = include_str!("input.txt"); + +mod part_1; +use part_1::part_1; +mod part_2; +use part_2::part_2; + +#[non_exhaustive] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum Op { + Noop, + AddX(i64), +} + +// Represents the cycle count +impl From for i64 { + fn from(op: Op) -> Self { + match op { + Op::Noop => 1, + Op::AddX(_) => 2, + } + } +} +impl From<&Op> for i64 { + fn from(op: &Op) -> Self { + match op { + Op::Noop => 1, + Op::AddX(_) => 2, + } + } +} + +impl From<&'static str> for Op { + fn from(s: &'static str) -> Self { + let bits = s.split(' ').collect::>(); + match bits[0] { + "noop" => Self::Noop, + "addx" => Self::AddX( + bits[1] + .parse::() + .expect("Non-numerical addx instruction"), + ), + _ => unreachable!("Unknown operation {:?}", bits), + } + } +} + +fn parse_input(input: &'static str) -> Vec { + input.lines().map(Op::from).collect() +} + +pub fn main() { + let input = parse_input(INPUT); + part_1(&input); + part_2(&input); +} diff --git a/rust/src/day10/part_1.rs b/rust/src/day10/part_1.rs new file mode 100644 index 0000000..6d20535 --- /dev/null +++ b/rust/src/day10/part_1.rs @@ -0,0 +1,49 @@ +use crate::Op; + +pub(crate) fn part_1(input: &[Op]) -> i64 { + let mut cycle = 0i64; + let mut register_x = 1; + + let mut values = [0; 6]; + for op in input { + for _ in 0..i64::from(op) { + cycle += 1; + match cycle { + 20 => values[0] = register_x * cycle, + 60 => values[1] = register_x * cycle, + 100 => values[2] = register_x * cycle, + 140 => values[3] = register_x * cycle, + 180 => values[4] = register_x * cycle, + 220 => values[5] = register_x * cycle, + _ => {} + } + } + + match op { + Op::Noop => {} + Op::AddX(x) => { + register_x += x; + } + } + } + + let result = values.iter().sum(); + println!("Part 1: {result}"); + + result +} + +#[cfg(test)] +mod tests { + const SAMPLE_INPUT: &str = include_str!("sample_input.txt"); + + #[test] + fn test_with_solution() { + assert_eq!(super::part_1(&crate::parse_input(crate::INPUT)), 14860); + } + + #[test] + fn test_with_sample_solution() { + assert_eq!(super::part_1(&crate::parse_input(SAMPLE_INPUT)), 13140); + } +} diff --git a/rust/src/day10/part_2.rs b/rust/src/day10/part_2.rs new file mode 100644 index 0000000..ca4e87e --- /dev/null +++ b/rust/src/day10/part_2.rs @@ -0,0 +1,89 @@ +use crate::Op; + +const SCREEN_WIDTH: usize = 40; +const SCREEN_HEIGHT: usize = 6; + +pub(crate) fn part_2(input: &[Op]) -> [String; SCREEN_HEIGHT] { + let mut cycle = 0i64; + let mut register_x = 1; + let mut current_line = 0; + + let mut result = [ + String::new(), + String::new(), + String::new(), + String::new(), + String::new(), + String::new(), + ]; + + for op in input { + for _ in 0..i64::from(op) { + match cycle { + 40 => current_line += 1, + 80 => current_line += 1, + 120 => current_line += 1, + 160 => current_line += 1, + 200 => current_line += 1, + _ => {} + } + cycle += 1; + + let corrected_x = (cycle - 1) - register_x - (current_line * SCREEN_WIDTH) as i64; + // println!( + // "cycle = {cycle}, register_x = {register_x}, current_line = {current_line}, corrected_x = {corrected_x}", + // ); + + result[current_line].push(match corrected_x { + -1 | 0 | 1 => '#', + _ => '.', + }); + } + + match op { + Op::Noop => {} + Op::AddX(x) => { + register_x += x; + } + } + } + + println!("Part2:\n{}", result.join("\n")); + + result +} + +#[cfg(test)] +mod tests { + const SAMPLE_INPUT: &str = include_str!("sample_input.txt"); + + #[test] + fn test_with_solution() { + assert_eq!( + super::part_2(&crate::parse_input(crate::INPUT)), + [ + "###...##..####.####.#..#.#..#.###..#..#.", + "#..#.#..#....#.#....#..#.#..#.#..#.#.#..", + "#..#.#......#..###..####.#..#.#..#.##...", + "###..#.##..#...#....#..#.#..#.###..#.#..", + "#.#..#..#.#....#....#..#.#..#.#.#..#.#..", + "#..#..###.####.####.#..#..##..#..#.#..#.", + ] + ); + } + + #[test] + fn test_with_sample_solution() { + assert_eq!( + super::part_2(&crate::parse_input(SAMPLE_INPUT)), + [ + "##..##..##..##..##..##..##..##..##..##..", + "###...###...###...###...###...###...###.", + "####....####....####....####....####....", + "#####.....#####.....#####.....#####.....", + "######......######......######......####", + "#######.......#######.......#######.....", + ] + ); + } +} diff --git a/rust/src/day10/sample_input.txt b/rust/src/day10/sample_input.txt new file mode 100644 index 0000000..94cd0a8 --- /dev/null +++ b/rust/src/day10/sample_input.txt @@ -0,0 +1,146 @@ +addx 15 +addx -11 +addx 6 +addx -3 +addx 5 +addx -1 +addx -8 +addx 13 +addx 4 +noop +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx -35 +addx 1 +addx 24 +addx -19 +addx 1 +addx 16 +addx -11 +noop +noop +addx 21 +addx -15 +noop +noop +addx -3 +addx 9 +addx 1 +addx -3 +addx 8 +addx 1 +addx 5 +noop +noop +noop +noop +noop +addx -36 +noop +addx 1 +addx 7 +noop +noop +noop +addx 2 +addx 6 +noop +noop +noop +noop +noop +addx 1 +noop +noop +addx 7 +addx 1 +noop +addx -13 +addx 13 +addx 7 +noop +addx 1 +addx -33 +noop +noop +noop +addx 2 +noop +noop +noop +addx 8 +noop +addx -1 +addx 2 +addx 1 +noop +addx 17 +addx -9 +addx 1 +addx 1 +addx -3 +addx 11 +noop +noop +addx 1 +noop +addx 1 +noop +noop +addx -13 +addx -19 +addx 1 +addx 3 +addx 26 +addx -30 +addx 12 +addx -1 +addx 3 +addx 1 +noop +noop +noop +addx -9 +addx 18 +addx 1 +addx 2 +noop +noop +addx 9 +noop +noop +noop +addx -1 +addx 2 +addx -37 +addx 1 +addx 3 +noop +addx 15 +addx -21 +addx 22 +addx -6 +addx 1 +noop +addx 2 +addx 1 +noop +addx -10 +noop +noop +addx 20 +addx 1 +addx 2 +addx 2 +addx -6 +addx -11 +noop +noop +noop \ No newline at end of file