From 3aff343f90a31c4dcf94c2f8348de211fd6d10fb Mon Sep 17 00:00:00 2001 From: timeshifter Date: Wed, 1 Jul 2026 19:31:30 +0200 Subject: [PATCH] add day 12 --- day12/Cargo.lock | 7 +++ day12/Cargo.toml | 6 ++ day12/example.txt | 6 ++ day12/input.txt | 23 +++++++ day12/src/main.rs | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+) create mode 100644 day12/Cargo.lock create mode 100644 day12/Cargo.toml create mode 100644 day12/example.txt create mode 100644 day12/input.txt create mode 100644 day12/src/main.rs diff --git a/day12/Cargo.lock b/day12/Cargo.lock new file mode 100644 index 0000000..f8bfcac --- /dev/null +++ b/day12/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "day12" +version = "0.1.0" diff --git a/day12/Cargo.toml b/day12/Cargo.toml new file mode 100644 index 0000000..ed2fcd9 --- /dev/null +++ b/day12/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day12" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/day12/example.txt b/day12/example.txt new file mode 100644 index 0000000..01a004b --- /dev/null +++ b/day12/example.txt @@ -0,0 +1,6 @@ +cpy 41 a +inc a +inc a +dec a +jnz a 2 +dec a diff --git a/day12/input.txt b/day12/input.txt new file mode 100644 index 0000000..3729d83 --- /dev/null +++ b/day12/input.txt @@ -0,0 +1,23 @@ +cpy 1 a +cpy 1 b +cpy 26 d +jnz c 2 +jnz 1 5 +cpy 7 c +inc d +dec c +jnz c -2 +cpy a c +inc a +dec b +jnz b -2 +cpy c b +dec d +jnz d -6 +cpy 19 c +cpy 11 d +inc a +dec d +jnz d -2 +dec c +jnz c -5 diff --git a/day12/src/main.rs b/day12/src/main.rs new file mode 100644 index 0000000..5f5c642 --- /dev/null +++ b/day12/src/main.rs @@ -0,0 +1,154 @@ +#[cfg(debug_assertions)] +const FILENAME: &str = "example.txt"; +#[cfg(not(debug_assertions))] +const FILENAME: &str = "input.txt"; + +fn main() { + let program: Vec<_> = std::fs::read_to_string(FILENAME) + .unwrap() + .lines() + .map(Instruction::parse) + .collect(); + + part1(&program); + part2(&program); +} + +struct Registers { + registers: [usize; 4], +} + +impl Registers { + fn set(&mut self, register: char, source: &Source) { + let address = Self::get_address(register); + match source { + Source::Register(from_register) => { + let from_address = Self::get_address(*from_register); + self.registers[address] = self.registers[from_address]; + } + Source::Value(value) => self.registers[address] = *value, + } + } + + fn inc(&mut self, register: char) { + let address = Self::get_address(register); + self.registers[address] += 1; + } + + fn dec(&mut self, register: char) { + let address = Self::get_address(register); + self.registers[address] -= 1; + } + + fn is_nonzero(&self, value: &Source) -> bool { + match value { + Source::Register(register) => { + let address = Self::get_address(*register); + self.registers[address] != 0 + } + Source::Value(value) => *value != 0, + } + } + + fn get_address(register: char) -> usize { + match register { + 'a' => 0, + 'b' => 1, + 'c' => 2, + 'd' => 3, + _ => panic!("unknown register: {register}"), + } + } + + fn new() -> Self { + Self { registers: [0; 4] } + } + + fn value_a(&self) -> usize { + let address = Self::get_address('a'); + self.registers[address] + } +} + +fn part1(program: &[Instruction]) { + let mut registers = Registers::new(); + + run_program(program, &mut registers); + println!("{}", registers.value_a()); +} + +fn part2(program: &[Instruction]) { + let mut registers = Registers::new(); + + registers.set('c', &Source::Value(1)); + + run_program(program, &mut registers); + println!("{}", registers.value_a()); +} + +fn run_program(program: &[Instruction], registers: &mut Registers) { + let mut pointer = 0; + + while let Some(instruction) = program.get(pointer) { + match instruction { + Instruction::Cpy(source, register) => { + registers.set(*register, source); + pointer += 1; + } + Instruction::Inc(register) => { + registers.inc(*register); + pointer += 1; + } + Instruction::Dec(register) => { + registers.dec(*register); + pointer += 1; + } + Instruction::Jnz(register, offset) => { + if registers.is_nonzero(register) { + pointer = (pointer as isize + offset) as usize; + } else { + pointer += 1; + } + } + } + } +} + +#[derive(Debug)] +enum Instruction { + Cpy(Source, char), + Inc(char), + Dec(char), + Jnz(Source, isize), +} + +#[derive(Debug)] +enum Source { + Register(char), + Value(usize), +} + +impl Source { + fn parse(s: &str) -> Self { + let first_char = s.chars().next().unwrap(); + if first_char.is_ascii_digit() { + Self::Value(s.parse().unwrap()) + } else { + Self::Register(first_char) + } + } +} + +impl Instruction { + fn parse(s: &str) -> Self { + let words: Vec<_> = s.split_whitespace().collect(); + dbg!(&words); + match words[0] { + "cpy" => Self::Cpy(Source::parse(words[1]), words[2].chars().next().unwrap()), + "inc" => Self::Inc(words[1].chars().next().unwrap()), + "dec" => Self::Dec(words[1].chars().next().unwrap()), + "jnz" => Self::Jnz(Source::parse(words[1]), words[2].parse().unwrap()), + _ => panic!("unknown pattern: {s}"), + } + } +}