From 48ad7e7a96e93fa971ebcb55e667b346f0d4b305 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 13 Nov 2023 19:52:52 +0100 Subject: [PATCH] Day 21 part 1. --- input/day21.txt | 32 +++++++ src/main.rs | 2 +- src/tasks/day21.rs | 211 +++++++++++++++++++++++++++++++++++++++++++++ src/tasks/mod.rs | 1 + 4 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 input/day21.txt create mode 100644 src/tasks/day21.rs diff --git a/input/day21.txt b/input/day21.txt new file mode 100644 index 0000000..2860f4c --- /dev/null +++ b/input/day21.txt @@ -0,0 +1,32 @@ +#ip 1 +seti 123 0 2 +bani 2 456 2 +eqri 2 72 2 +addr 2 1 1 +seti 0 0 1 +seti 0 3 2 +bori 2 65536 5 +seti 4843319 1 2 +bani 5 255 4 +addr 2 4 2 +bani 2 16777215 2 +muli 2 65899 2 +bani 2 16777215 2 +gtir 256 5 4 +addr 4 1 1 +addi 1 1 1 +seti 27 4 1 +seti 0 7 4 +addi 4 1 3 +muli 3 256 3 +gtrr 3 5 3 +addr 3 1 1 +addi 1 1 1 +seti 25 0 1 +addi 4 1 4 +seti 17 0 1 +setr 4 1 5 +seti 7 3 1 +eqrr 2 0 4 +addr 4 1 1 +seti 5 3 1 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9d553c6..6c2914f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,3 @@ fn main() { - aoc_2018::tasks::day19::task2(); + aoc_2018::tasks::day21::task1(); } diff --git a/src/tasks/day21.rs b/src/tasks/day21.rs new file mode 100644 index 0000000..f8f6b0e --- /dev/null +++ b/src/tasks/day21.rs @@ -0,0 +1,211 @@ +use std::ops::{BitAnd, BitOr}; + +pub fn task1() { + let input = include_str!("../../input/day21.txt"); + let result = run1(input, 0); + println!("{result:?}"); +} + +fn run1(input: &str, start_value: i64) -> (i64, usize) { + let (config, program) = input.split_once("\n").unwrap(); + let ip_register: usize = config.split_once(" ").unwrap().1.parse().unwrap(); + + let program: Vec = program.lines().map(parse_instruction).collect(); + + let mut registers: Registers = [start_value, 0, 0, 0, 0, 0]; + let mut ip = 0; + let mut count = 0usize; + loop { + //print!("ip={ip}, {registers:?}"); + + registers[ip_register] = ip as i64; + let instruction = program.get(ip).unwrap(); + + //print!("{instruction:?}"); + + let op: Op = instruction.opcode; + registers = op.process(registers, *instruction); + + //println!("{registers:?}"); + + ip = registers[ip_register] as usize; + ip += 1; + + // uncomment this and print look at register 2 to find the value for register 0 + // that would cause the program to halt + if ip == 28 { + println!("{registers:?}"); + break; + } + + if program.get(ip).is_none() { + break; + } + count += 1; + } + println!("executed instructions: {count}"); + (registers[0], count) +} + +fn parse_instruction(instruction: &str) -> Instruction { + let instruction: Vec<_> = instruction.split(" ").collect(); + let opcode = match instruction[0] { + "addr" => Op::AddR, + "addi" => Op::AddI, + "mulr" => Op::MulR, + "muli" => Op::MulI, + "banr" => Op::BanR, + "bani" => Op::BanI, + "borr" => Op::BorR, + "bori" => Op::BorI, + "setr" => Op::SetR, + "seti" => Op::SetI, + "gtir" => Op::GtIR, + "gtri" => Op::GtRI, + "gtrr" => Op::GtRR, + "eqir" => Op::EqIR, + "eqri" => Op::EqRI, + "eqrr" => Op::EqRR, + &_ => { + panic!("unknown op {}", instruction[0]) + } + }; + let instruction = Instruction { + opcode, + a: instruction[1].parse().unwrap(), + b: instruction[2].parse().unwrap(), + c: instruction[3].parse().unwrap(), + }; + instruction +} + +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +enum Op { + AddR, + AddI, + MulR, + MulI, + BanR, + BanI, + BorR, + BorI, + SetR, + SetI, + GtIR, + GtRI, + GtRR, + EqIR, + EqRI, + EqRR, +} + +impl Op { + fn process(&self, registers: Registers, instruction: Instruction) -> Registers { + let mut result = registers.clone(); + + match self { + Op::AddR => { + result[instruction.c] = result[instruction.a] + result[instruction.b]; + } + Op::AddI => { + result[instruction.c] = result[instruction.a] + instruction.b as i64; + } + Op::MulR => { + result[instruction.c] = result[instruction.a] * result[instruction.b]; + } + Op::MulI => { + result[instruction.c] = result[instruction.a] * instruction.b as i64; + } + Op::BanR => { + result[instruction.c] = result[instruction.a].bitand(result[instruction.b]); + } + Op::BanI => { + result[instruction.c] = result[instruction.a].bitand(instruction.b as i64); + } + Op::BorR => { + result[instruction.c] = result[instruction.a].bitor(result[instruction.b]); + } + Op::BorI => { + result[instruction.c] = result[instruction.a].bitor(instruction.b as i64); + } + Op::SetR => { + result[instruction.c] = result[instruction.a]; + } + Op::SetI => { + result[instruction.c] = instruction.a as i64; + } + Op::GtIR => { + result[instruction.c] = if instruction.a as i64 > result[instruction.b] { + 1 + } else { + 0 + } + } + Op::GtRI => { + result[instruction.c] = if result[instruction.a] > instruction.b as i64 { + 1 + } else { + 0 + } + } + Op::GtRR => { + result[instruction.c] = if result[instruction.a] > result[instruction.b] { + 1 + } else { + 0 + } + } + Op::EqIR => { + result[instruction.c] = if instruction.a as i64 == result[instruction.b] { + 1 + } else { + 0 + } + } + Op::EqRI => { + result[instruction.c] = if result[instruction.a] == instruction.b as i64 { + 1 + } else { + 0 + } + } + Op::EqRR => { + result[instruction.c] = if result[instruction.a] == result[instruction.b] { + 1 + } else { + 0 + } + } + } + + result + } +} + +type Registers = [i64; 6]; + +#[derive(Copy, Clone, Debug)] +struct Instruction { + opcode: Op, + a: usize, + b: usize, + c: usize, +} + +#[cfg(test)] +mod test { + use crate::tasks::day21::run1; + + #[test] + fn example1() { + let input = "#ip 0\n\ + seti 5 0 1\n\ + seti 6 0 2\n\ + addi 0 1 0\n\ + addr 1 2 3\n\ + setr 1 0 0\n\ + seti 8 0 4\n\ + seti 9 0 5"; + assert_eq!(run1(input, 0).0, 6); + } +} diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index bbd2439..d5bc06f 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -18,6 +18,7 @@ pub mod day17; pub mod day18; pub mod day19; pub mod day20; +pub mod day21; pub mod day22; pub mod day23; pub mod day24;