summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillermo Ramos2025-01-12 17:44:14 +0100
committerGuillermo Ramos2025-01-12 23:45:56 +0100
commit5d9eaa96f4c1c30b6d7f1c2df5ba914402731e9a (patch)
tree00f3b87a1f1070e16ecfa8d8d9631077b4cc5998
parent59f7d2662a4d6c5faa2beda007de9ee5a9a108d6 (diff)
downloadAoC-5d9eaa96f4c1c30b6d7f1c2df5ba914402731e9a.tar.gz
2024.17 (part 1 only)HEADmaster
-rw-r--r--2024_rust/inputs/175
-rw-r--r--2024_rust/src/bin/day17.rs179
2 files changed, 184 insertions, 0 deletions
diff --git a/2024_rust/inputs/17 b/2024_rust/inputs/17
new file mode 100644
index 0000000..02a6fbe
--- /dev/null
+++ b/2024_rust/inputs/17
@@ -0,0 +1,5 @@
+Register A: 64751475
+Register B: 0
+Register C: 0
+
+Program: 2,4,1,2,7,5,4,5,1,3,5,5,0,3,3,0
diff --git a/2024_rust/src/bin/day17.rs b/2024_rust/src/bin/day17.rs
new file mode 100644
index 0000000..6c9bf1a
--- /dev/null
+++ b/2024_rust/src/bin/day17.rs
@@ -0,0 +1,179 @@
+use regex::Regex;
+use std::fmt;
+
+#[derive(Clone)]
+struct Device {
+ a: u64,
+ b: u64,
+ c: u64,
+ program: Vec<u8>,
+ ip: usize,
+ output: Vec<u8>,
+}
+
+impl Device {
+ fn parse(input: &str) -> Device {
+ let mut a: u64 = 0;
+ let mut b: u64 = 0;
+ let mut c: u64 = 0;
+ let mut program: Vec<u8> = vec![];
+ let re = Regex::new(r"Register ([ABC]): ([0-9]+)|Program: ([0-9,]+)").unwrap();
+ for cap in re.captures_iter(input) {
+ if let Some(opcodes) = cap.get(3) {
+ program = opcodes
+ .as_str()
+ .split(",")
+ .map(|op| op.parse().unwrap())
+ .collect();
+ continue;
+ } else {
+ match &cap[1] {
+ "A" => a = cap[2].parse().unwrap(),
+ "B" => b = cap[2].parse().unwrap(),
+ "C" => c = cap[2].parse().unwrap(),
+ _ => unreachable!(),
+ }
+ }
+ }
+ Device {
+ a,
+ b,
+ c,
+ program,
+ ip: 0,
+ output: vec![],
+ }
+ }
+
+ fn instruction(&self) -> Option<(Instruction, u8)> {
+ if self.ip < self.program.len() {
+ Some((self.program[self.ip].into(), self.program[self.ip + 1]))
+ } else {
+ None
+ }
+ }
+
+ fn read_next_instruction(&mut self) -> Option<(Instruction, u8)> {
+ let res = self.instruction();
+ if res.is_some() {
+ self.ip += 2;
+ }
+ res
+ }
+
+ fn get_combo(&self, op: u8) -> u64 {
+ match op {
+ 0..=3 => op as u64,
+ 4 => self.a,
+ 5 => self.b,
+ 6 => self.c,
+ _ => unimplemented!(),
+ }
+ }
+
+ fn output(&self) -> String {
+ self.output
+ .iter()
+ .map(|n| format!("{}", n))
+ .collect::<Vec<_>>()
+ .join(",")
+ }
+
+ fn step(&mut self) -> bool {
+ // println!("{}", self);
+ let Some((instruction, operand)) = self.read_next_instruction() else {
+ return false;
+ };
+ match instruction {
+ Adv => self.a /= 2u64.pow(self.get_combo(operand) as u32),
+ Bxl => self.b ^= operand as u64,
+ Bst => self.b = self.get_combo(operand) % 8,
+ Jnz => {
+ if self.a != 0 {
+ self.ip = operand as usize;
+ }
+ }
+ Bxc => self.b ^= self.c,
+ Out => self.output.push((self.get_combo(operand) % 8) as u8),
+ Bdv => self.b = self.a / 2u64.pow(self.get_combo(operand) as u32),
+ Cdv => self.c = self.a / 2u64.pow(self.get_combo(operand) as u32),
+ };
+ true
+ }
+
+ fn run(&mut self) -> String {
+ while self.step() {}
+ self.output()
+ }
+}
+
+#[derive(Debug)]
+enum Instruction {
+ Adv,
+ Bxl,
+ Bst,
+ Jnz,
+ Bxc,
+ Out,
+ Bdv,
+ Cdv,
+}
+use Instruction::*;
+
+impl From<u8> for Instruction {
+ fn from(item: u8) -> Instruction {
+ match item {
+ 0 => Adv,
+ 1 => Bxl,
+ 2 => Bst,
+ 3 => Jnz,
+ 4 => Bxc,
+ 5 => Out,
+ 6 => Bdv,
+ 7 => Cdv,
+ _ => panic!(),
+ }
+ }
+}
+
+impl fmt::Display for Device {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ writeln!(f, "Registers: A={} B={} C={}", self.a, self.b, self.c)?;
+ writeln!(f, "{:?}", self.program)?;
+ let spaces = 1 + 3 * self.ip;
+ let curri = match self.instruction() {
+ Some((i, op)) => {
+ let combo = self.get_combo(op);
+ if op < 4 {
+ format!(" {i:?}({op})")
+ } else {
+ format!(" {i:?}({op}) (combo: {combo})")
+ }
+ }
+ None => "".to_string(),
+ };
+ writeln!(
+ f,
+ "{}^{}",
+ (0..spaces).map(|_| " ").collect::<String>(),
+ curri
+ )?;
+ writeln!(f, "Output: {:?}", self.output())
+ }
+}
+
+fn p1(input: &str) -> String {
+ let mut dev = Device::parse(input);
+ let result = dev.run();
+ result.to_string()
+}
+
+fn p2(_input: &str) -> String {
+ let result = "TODO";
+
+ result.to_string()
+}
+
+fn main() {
+ aoc2024::run_day("17", p1, p2);
+}