From 2f0830168c8767a2e39d7c920a3dc9ecd12113b6 Mon Sep 17 00:00:00 2001 From: alex <> Date: Tue, 17 Dec 2024 09:22:18 +0100 Subject: [PATCH] Day17 - part 1 --- src/day17.rs | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 2 + 2 files changed, 171 insertions(+) create mode 100644 src/day17.rs diff --git a/src/day17.rs b/src/day17.rs new file mode 100644 index 0000000..9208ae0 --- /dev/null +++ b/src/day17.rs @@ -0,0 +1,169 @@ +use std::error::Error; +use std::path::Path; + +struct Computer { + regA: u64, + regB: u64, + regC: u64, + prgm: Vec, + ptr: usize, + out: Vec, +} + +impl Computer { + pub fn new(input: &str) -> Self { + let (regs, mut prgm) = input.split_once("\n\n").unwrap(); + + let regs: Vec = regs.split("\n") + .map(|l| l[12..l.len()].parse::().unwrap()) + .collect(); + let regA = regs[0]; + let regB = regs[1]; + let regC = regs[2]; + + if prgm.ends_with("\n") { + prgm = &prgm[0..prgm.len()-1]; + } + + let prgm: Vec = prgm[9..prgm.len()].split(",") + .map(|v| v.parse::().unwrap()) + .collect(); + let ptr = 0; + let out = Vec::new(); + + Self { regA, regB, regC, prgm, ptr, out } + } + + fn adv(&self, num: u64, operand: u8) -> u64 { + num / 2_u64.pow(self.combo(operand) as u32) + } + + fn combo(&self, operand: u8) -> u64 { + match operand { + 0 | 1 | 2 | 3 => operand as u64, + 4 => self.regA, + 5 => self.regB, + 6 => self.regC, + _ => unreachable!(), + } + } + + fn run(&mut self) { + while self.ptr < self.prgm.len() { + let opcode = self.prgm[self.ptr]; + let operand = self.prgm[self.ptr + 1]; + match opcode { + 0 => self.regA = self.adv(self.regA, operand), + 1 => self.regB ^= operand as u64, + 2 => self.regB = self.combo(operand) % 8, + 3 => { + if self.regA != 0 { + self.ptr = operand as usize; + continue; + } + }, + 4 => self.regB ^= self.regC, + 5 => self.out.push((self.combo(operand) % 8) as u8), + 6 => self.regB = self.adv(self.regA, operand), + 7 => self.regC = self.adv(self.regA, operand), + _ => {} + } + self.ptr += 2; + } + //println!("regA={} regB={} regC={} {:?}", self.regA, self.regB, self.regC, self.out); + } + + fn print(&self) -> String { + let s: Vec = self.out.iter() + .map(|v| v.to_string()) + .collect(); + s.join(",") + } +} + +fn run_part1(input: &str) -> Result> { + println!("Running {} - part 1", get_day()); + + let mut computer = Computer::new(input); + computer.run(); + Ok(computer.print()) +} + +fn run_part2(input: &str) -> Result> { + println!("Running {} - part 2", get_day()); + + let res = "".to_string(); + Ok(res) +} + +pub fn run(input: &str) -> Result<(), Box> { + let res = run_part1(input)?; + println!("{res}"); + + let res = run_part2(input)?; + println!("{res}"); + + Ok(()) +} + +fn get_day() -> String { + let filename = file!(); + Path::new(filename).file_stem().unwrap().to_str().unwrap().to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + + static TEXT_INPUT_0: &str = "\ +Register A: 0 +Register B: 0 +Register C: 9 + +Program: 2,6"; + static TEXT_INPUT_1: &str = "\ +Register A: 10 +Register B: 0 +Register C: 0 + +Program: 5,0,5,1,5,4"; + static TEXT_INPUT_2: &str = "\ +Register A: 2024 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0"; + static TEXT_INPUT_3: &str = "\ +Register A: 0 +Register B: 29 +Register C: 0 + +Program: 1,7"; + static TEXT_INPUT_4: &str = "\ +Register A: 0 +Register B: 2024 +Register C: 43690 + +Program: 4,0"; + static TEXT_INPUT_5: &str = "\ +Register A: 729 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0"; + + #[test] + fn test_part1() { + assert_eq!("", run_part1(TEXT_INPUT_0).unwrap()); + assert_eq!("0,1,2", run_part1(TEXT_INPUT_1).unwrap()); + assert_eq!("4,2,5,6,7,7,7,7,3,1,0", run_part1(TEXT_INPUT_2).unwrap()); + assert_eq!("", run_part1(TEXT_INPUT_3).unwrap()); + assert_eq!("", run_part1(TEXT_INPUT_4).unwrap()); + assert_eq!("4,6,3,5,6,3,5,2,1,0", run_part1(TEXT_INPUT_5).unwrap()); + } + + #[test] + fn test_part2() { + assert_eq!("", run_part2(TEXT_INPUT_5).unwrap()); + } +} diff --git a/src/main.rs b/src/main.rs index 55d2ac4..f34e9c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ pub mod day13; pub mod day14; pub mod day15; pub mod day16; +pub mod day17; fn main() { let args: Vec = env::args().collect(); @@ -58,6 +59,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box> { "day14" => day14::run(&input)?, "day15" => day15::run(&input)?, "day16" => day16::run(&input)?, + "day17" => day17::run(&input)?, _ => return Err(format!("unknown or unimplemented day \"{day}\"").into()), } Ok(()) -- 2.39.5