From 6d04837a924cc606e7970e02877834fc5b8d70ce Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Tue, 17 Dec 2024 13:24:10 +0200 Subject: [PATCH] feat: day17 partly * part two has non-viable bruteforcing going on, i'll figure it out later --- input/day17/example | 5 + input/day17/example2 | 5 + src/day17/mod.rs | 246 +++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 8 ++ 4 files changed, 264 insertions(+) create mode 100644 input/day17/example create mode 100644 input/day17/example2 create mode 100644 src/day17/mod.rs diff --git a/input/day17/example b/input/day17/example new file mode 100644 index 0000000..f09839b --- /dev/null +++ b/input/day17/example @@ -0,0 +1,5 @@ +Register A: 729 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0 diff --git a/input/day17/example2 b/input/day17/example2 new file mode 100644 index 0000000..4a91c26 --- /dev/null +++ b/input/day17/example2 @@ -0,0 +1,5 @@ +Register A: 2024 +Register B: 0 +Register C: 0 + +Program: 0,3,5,4,3,0 diff --git a/src/day17/mod.rs b/src/day17/mod.rs new file mode 100644 index 0000000..215f804 --- /dev/null +++ b/src/day17/mod.rs @@ -0,0 +1,246 @@ +use std::{ + fs::File, + io::{BufRead, BufReader}, + path::Path, + str::FromStr, +}; + +pub fn solve(input: &Path) -> anyhow::Result<()> { + println!("part one: {}", part_one(input)?); + println!("part two: {}", part_two(input)?); + + Ok(()) +} + +#[derive(Debug)] +enum ProgramPart { + Instruction(Ins), + LiteralOperand(usize), +} + +#[derive(Debug)] +enum Ins { + Adv, + Bxl, + Bst, + Jnz, + Bxc, + Out, + Bdv, + Cdv, +} + +impl FromStr for Ins { + type Err = Box; + fn from_str(s: &str) -> Result { + match s { + "0" => Ok(Self::Adv), + "1" => Ok(Self::Bxl), + "2" => Ok(Self::Bst), + "3" => Ok(Self::Jnz), + "4" => Ok(Self::Bxc), + "5" => Ok(Self::Out), + "6" => Ok(Self::Bdv), + "7" => Ok(Self::Cdv), + _ => unreachable!(), + } + } +} + +#[derive(Debug)] +enum Copr { + Literal(usize), + RA, + RB, + RC, +} + +impl Copr { + fn from_usize(n: usize) -> Self { + match n { + 0 => Self::Literal(0), + 1 => Self::Literal(1), + 2 => Self::Literal(2), + 3 => Self::Literal(3), + 4 => Self::RA, + 5 => Self::RB, + 6 => Self::RC, + _ => unreachable!(), + } + } + + fn real(&self, ra: i32, rb: i32, rc: i32) -> i32 { + match self { + Self::Literal(n) => *n as i32, + Self::RA => ra, + Self::RB => rb, + Self::RC => rc, + } + } +} + +fn part_one(input: &Path) -> anyhow::Result { + let reader = BufReader::new(File::open(input)?); + + let mut ra: i32 = 0; + let mut rb: i32 = 0; + let mut rc: i32 = 0; + let mut program: Vec = vec![]; + for line in reader.lines() { + let line = line?; + if line.starts_with("Register A") { + ra = line.split_whitespace().last().unwrap().parse()?; + } else if line.starts_with("Register B") { + rb = line.split_whitespace().last().unwrap().parse()?; + } else if line.starts_with("Register C") { + rc = line.split_whitespace().last().unwrap().parse()?; + } else if line.starts_with("Program") { + program.append( + &mut line + .split_whitespace() + .last() + .unwrap() + .split(",") + .enumerate() + .filter_map(|(i, c)| { + if c == "," { + None + } else if i % 2 == 0 { + Some(ProgramPart::Instruction(c.parse().unwrap())) + } else { + Some(ProgramPart::LiteralOperand(c.parse().unwrap())) + } + }) + .collect::>(), + ); + } + } + + let mut out: Vec = vec![]; + let mut ptr = 0; + while ptr < program.len() { + let mut incr = true; + + if let ProgramPart::Instruction(ins) = &program[ptr] { + if let ProgramPart::LiteralOperand(lit_opr) = &program[ptr + 1] { + let combo_opr = Copr::from_usize(*lit_opr).real(ra, rb, rc); + match &ins { + Ins::Adv => ra /= 2_i32.pow(combo_opr as u32), + Ins::Bxl => rb ^= *lit_opr as i32, + Ins::Bst => rb = combo_opr % 8, + Ins::Jnz => { + if ra != 0 { + ptr = *lit_opr; + incr = false; + } + } + Ins::Bxc => rb ^= rc, + Ins::Out => out.push(combo_opr % 8), + Ins::Bdv => rb = ra / 2_i32.pow(combo_opr as u32), + Ins::Cdv => rc = ra / 2_i32.pow(combo_opr as u32), + } + } else { + unreachable!(); + } + } else { + unreachable!(); + } + + if incr { + ptr += 2; + } + } + + Ok(out + .iter() + .map(|o| o.to_string()) + .collect::>() + .join(",")) +} + +fn part_two(input: &Path) -> anyhow::Result { + let reader = BufReader::new(File::open(input)?); + + let mut original_program = String::new(); + let mut program: Vec = vec![]; + for line in reader.lines() { + let line = line?; + if line.starts_with("Program") { + original_program = line.split_whitespace().last().unwrap().into(); + program = original_program + .clone() + .split(",") + .enumerate() + .filter_map(|(i, c)| { + if c == "," { + None + } else if i % 2 == 0 { + Some(ProgramPart::Instruction(c.parse().unwrap())) + } else { + Some(ProgramPart::LiteralOperand(c.parse().unwrap())) + } + }) + .collect::>(); + } + } + + let mut ra_init = 8; + let mut ra: i32; + let mut rb: i32; + let mut rc: i32; + loop { + ra_init += 1; + ra = ra_init; + rb = 0; + rc = 0; + + println!("trying {}", ra_init); + + let mut out: Vec = vec![]; + let mut ptr = 0; + while ptr < program.len() { + let mut incr = true; + + if let ProgramPart::Instruction(ins) = &program[ptr] { + if let ProgramPart::LiteralOperand(lit_opr) = &program[ptr + 1] { + let combo_opr = Copr::from_usize(*lit_opr).real(ra, rb, rc); + match &ins { + Ins::Adv => ra /= 2_i32.pow(combo_opr as u32), + Ins::Bxl => rb ^= *lit_opr as i32, + Ins::Bst => rb = combo_opr % 8, + Ins::Jnz => { + if ra != 0 { + ptr = *lit_opr; + incr = false; + } + } + Ins::Bxc => rb ^= rc, + Ins::Out => out.push(combo_opr % 8), + Ins::Bdv => rb = ra / 2_i32.pow(combo_opr as u32), + Ins::Cdv => rc = ra / 2_i32.pow(combo_opr as u32), + } + } else { + unreachable!(); + } + } else { + unreachable!(); + } + + if incr { + ptr += 2; + } + } + + let out_str = out + .iter() + .map(|o| o.to_string()) + .collect::>() + .join(","); + + if out_str == original_program { + break; + } + } + + Ok(ra_init) +} diff --git a/src/main.rs b/src/main.rs index 3d5ec77..fb5db83 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod day12; mod day13; mod day14; mod day15; +mod day17; mod day2; mod day3; mod day4; @@ -86,6 +87,10 @@ enum DayArgs { #[arg(short)] input: PathBuf, }, + Day17 { + #[arg(short)] + input: PathBuf, + }, } fn main() -> anyhow::Result<()> { @@ -137,6 +142,9 @@ fn main() -> anyhow::Result<()> { DayArgs::Day15 { input } => { day15::solve(&input)?; } + DayArgs::Day17 { input } => { + day17::solve(&input)?; + } } Ok(()) -- 2.44.1