From c99d8a400a27a85b8c31778f1b7c546aabdaaf10 Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Mon, 16 Dec 2024 22:29:36 -0800 Subject: [PATCH] day17: part 1 solution --- .aoc_tiles/tiles/2024/17.png | Bin 3105 -> 6327 bytes README.md | 5 +- src/day17.rs | 271 +++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 src/day17.rs diff --git a/.aoc_tiles/tiles/2024/17.png b/.aoc_tiles/tiles/2024/17.png index 4bbf39adbff0f1660878ec04cce1b31a8a07b065..353a003c333530c095e03398a108b33d1af35f97 100644 GIT binary patch literal 6327 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

- 2024 - 32 ⭐ - Rust + 2024 - 33 ⭐ - Rust

@@ -50,4 +50,7 @@ + + + diff --git a/src/day17.rs b/src/day17.rs new file mode 100644 index 0000000..8fe87a9 --- /dev/null +++ b/src/day17.rs @@ -0,0 +1,271 @@ +use std::{ops::BitXor, str::FromStr}; + +use aoc_runner_derive::aoc; +use itertools::Itertools; +use regex::Regex; + +#[derive(Debug, Clone, Copy)] +enum Register { + A = 0, + B = 1, + C = 2, +} +impl From for Register { + fn from(value: usize) -> Self { + match value { + 0 => Register::A, + 1 => Register::B, + 2 => Register::C, + v => panic!("invalid register address {}", v), + } + } +} + +#[derive(Debug, Clone, Copy)] +enum Opcode { + adv = 0, + bxl = 1, + bst = 2, + jnz = 3, + bxc = 4, + out = 5, + bdv = 6, + cdv = 7, +} + +impl From for Opcode { + fn from(value: usize) -> Self { + match value { + 0 => Opcode::adv, + 1 => Opcode::bxl, + 2 => Opcode::bst, + 3 => Opcode::jnz, + 4 => Opcode::bxc, + 5 => Opcode::out, + 6 => Opcode::bdv, + 7 => Opcode::cdv, + v => panic!("invalid opcode {}", v), + } + } +} + +impl Opcode { + fn interp_operand(&self, value: i64) -> Operand { + match self { + Self::adv | Self::bst | Self::out | Self::bdv | Self::cdv => Operand::new_combo(value), + Self::bxl | Self::jnz => Operand::Literal(value), + Self::bxc => Operand::Ignore, + } + } +} + +#[derive(Debug, Clone, Copy)] +enum Operand { + Literal(i64), + Load(Register), + Ignore, +} + +impl Operand { + fn new_combo(value: i64) -> Self { + match value { + 0..=3 => Operand::Literal(value), + 4 => Operand::Load(Register::A), + 5 => Operand::Load(Register::B), + 6 => Operand::Load(Register::C), + 7 => panic!("reserved combo operand 7"), + i => panic!("invalid combo operand {}", i), + } + } + fn value(self, m: &Machine) -> i64 { + match self { + Self::Literal(i) => i, + Self::Load(reg) => *m.registers.load(reg), + Self::Ignore => panic!("can't read ignored operand"), + } + } + fn is_literal(self) -> bool { + match self { + Self::Literal(_) => true, + _ => false, + } + } +} + +#[derive(Debug)] +struct RegisterFile { + file: [T; SIZE], +} + +impl RegisterFile { + fn load(&self, reg: Register) -> &T { + &self.file[reg as usize] + } + fn store(&mut self, reg: Register, val: T) { + self.file[reg as usize] = val; + } +} + +#[derive(Debug, Copy, Clone)] +struct Instruction { + opcode: Opcode, + operand: Operand, +} + +impl Instruction { + fn new(opcode: Opcode, operand: Operand) -> Self { + Self { opcode, operand } + } + fn exec(&self, m: &mut Machine) { + match self.opcode { + Opcode::adv => self.adv(m), + Opcode::bxl => self.bxl(m), + Opcode::bst => self.bst(m), + Opcode::jnz => self.jnz(m), + Opcode::bxc => self.bxc(m), + Opcode::out => self.out(m), + Opcode::bdv => self.bdv(m), + Opcode::cdv => self.cdv(m), + + _ => unimplemented!(), + } + } + fn adv(&self, m: &mut Machine) { + let num = m.registers.load(Register::A); + let denom = 1 << self.operand.value(m); + m.registers.store(Register::A, num / denom); + m.advance(); + } + fn bxl(&self, m: &mut Machine) { + let lhs = self.operand.value(m); + let rhs = m.registers.load(Register::B); + m.registers.store(Register::B, lhs.bitxor(rhs)); + m.advance(); + } + fn bst(&self, m: &mut Machine) { + m.registers.store(Register::B, self.operand.value(m) % 8); + m.advance(); + } + fn jnz(&self, m: &mut Machine) { + if *m.registers.load(Register::A) == 0 { + m.advance(); + } else { + m.jump(self.operand.value(m) as usize); + } + } + fn bxc(&self, m: &mut Machine) { + let a = m.registers.load(Register::B); + let b = m.registers.load(Register::C); + m.registers.store(Register::B, a.bitxor(b)); + m.advance(); + } + fn out(&self, m: &mut Machine) { + m.out_file.push(self.operand.value(m) % 8); + m.advance(); + } + fn bdv(&self, m: &mut Machine) { + let num = m.registers.load(Register::A); + let denom = 1 << self.operand.value(m); + m.registers.store(Register::B, num / denom); + m.advance(); + } + fn cdv(&self, m: &mut Machine) { + let num = m.registers.load(Register::A); + let denom = 1 << self.operand.value(m); + m.registers.store(Register::C, num / denom); + m.advance(); + } +} + +#[derive(Debug)] +struct Machine { + registers: RegisterFile<3, i64>, + program: Vec, + ip: usize, + out_file: Vec, +} + +impl Machine { + fn run(&mut self) { + let program = self.program.clone(); + loop { + if let Some(inst) = program.get(self.ip) { + inst.exec(self); + } else { + break; + } + } + } + fn advance(&mut self) { + self.ip += 1; + } + fn jump(&mut self, addr: usize) { + self.ip = addr; + } +} + +fn parse(input: &str) -> Machine { + let reg_re = Regex::new(r"Register ([ABC]): (\d+)").unwrap(); + let prog_re = Regex::new(r"Program: ((\d+,)*\d+)").unwrap(); + + let mut registers: RegisterFile<3, i64> = RegisterFile { file: [0; 3] }; + let mut program = Vec::new(); + for line in input.lines() { + if let Some(caps) = reg_re.captures(line) { + let address = (caps[1].as_bytes()[0] - b'A') as usize; + let value = caps[2].parse().unwrap(); + registers.store(address.into(), value); + continue; + } + if let Some(caps) = prog_re.captures(line) { + let instructions = caps[1].split(','); + for (inst, operand) in instructions.tuples() { + let opcode: Opcode = inst.parse::().unwrap().into(); + let operand = operand.parse::().unwrap().into(); + program.push(Instruction { + operand: opcode.interp_operand(operand), + opcode, + }); + } + } + } + + Machine { + registers, + program, + out_file: Vec::new(), + ip: 0, + } +} + +#[aoc(day17, part1)] +pub fn part1(input: &str) -> String { + let mut machine = parse(input); + machine.run(); + machine.out_file.iter().map(|n| n.to_string()).join(",") +} + +#[aoc(day17, part2)] +pub fn part2(input: &str) -> i64 { + 0 +} + +#[cfg(test)] +mod tests { + use super::*; + const EXAMPLE: &str = "Register A: 729 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0"; + + #[test] + fn part1_example() { + assert_eq!(part1(EXAMPLE), "4,6,3,5,6,3,5,2,1,0"); + } + + #[test] + fn part2_example() { + assert_eq!(part2(EXAMPLE), 0); + } +} diff --git a/src/lib.rs b/src/lib.rs index 345ea54..bbb9f15 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod day17; mod day16; use aoc_runner_derive::aoc_lib;