Skip to content

Commit 19293dd

Browse files
committed
Day 17 part 1 Rust solution
1 parent 64e7fbc commit 19293dd

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

day-17/Cargo.toml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "day-17"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
regex = "*"
8+
9+
[[bin]]
10+
name = "17-1"
11+
path = "src/17-1.rs"

day-17/src/17-1.rs

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use std::collections::{HashMap, VecDeque};
2+
use std::fmt::{Display, Formatter, Result};
3+
use std::fs;
4+
use regex::Regex;
5+
6+
#[derive(Debug)]
7+
struct CPU {
8+
regs: HashMap<char, u32>,
9+
program: Vec<u32>,
10+
ip: usize,
11+
output: Vec<u32>,
12+
}
13+
14+
impl CPU {
15+
fn new() -> CPU {
16+
CPU {
17+
regs: HashMap::new(),
18+
program: vec![],
19+
ip: 0,
20+
output: vec![],
21+
}
22+
}
23+
24+
fn load_reg(&mut self, reg: &char, value: u32) {
25+
self.regs.insert(*reg, value);
26+
}
27+
28+
fn load_program(&mut self, program: Vec<u32>) {
29+
self.program = program;
30+
}
31+
32+
fn combo(&self, op: u32) -> u32 {
33+
match op {
34+
0..=3 => op,
35+
4 => self.regs[&'a'],
36+
5 => self.regs[&'b'],
37+
6 => self.regs[&'c'],
38+
_ => panic!("Illegal combo operator: {op}.")
39+
}
40+
}
41+
42+
fn step(&mut self) -> bool {
43+
if self.ip >= self.program.len() { return false; }
44+
45+
let insn = self.program[self.ip];
46+
self.ip += 1;
47+
let op = self.program[self.ip];
48+
self.ip += 1;
49+
50+
match insn {
51+
0 => { self.regs.insert('a', self.regs[&'a'] / 2_u32.pow(self.combo(op))); },
52+
1 => { self.regs.insert('b', self.regs[&'b'] ^ op); },
53+
2 => { self.regs.insert('b', self.combo(op) % 8); },
54+
3 => { if self.regs[&'a'] != 0 { self.ip = op as usize; }; },
55+
4 => { self.regs.insert('b', self.regs[&'b'] ^ self.regs[&'c']); },
56+
5 => { self.output.push(self.combo(op) % 8); },
57+
6 => { self.regs.insert('b', self.regs[&'a'] / 2_u32.pow(self.combo(op))); },
58+
7 => { self.regs.insert('c', self.regs[&'a'] / 2_u32.pow(self.combo(op))); },
59+
_ => { panic!("Illegal opcode: {op}."); },
60+
};
61+
true
62+
}
63+
}
64+
65+
impl Display for CPU {
66+
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
67+
write!(f, "<CPU:\n")?;
68+
for (reg, value) in self.regs.iter() {
69+
write!(f, "{}={}\n", reg, value)?;
70+
}
71+
write!(f, "IP={}", self.ip)?;
72+
write!(f, "\nProgram: ")?;
73+
for inst in self.program.iter() {
74+
write!(f, "{} ", inst)?;
75+
}
76+
write!(f, "\nOutput: ")?;
77+
for out in self.output.iter() {
78+
write!(f, "{} ", out)?;
79+
}
80+
write!(f, "\n>")?;
81+
Ok(())
82+
}
83+
}
84+
85+
fn main() {
86+
let input = fs::read_to_string("../17.input").unwrap();
87+
88+
let reg_format = Regex::new(r"^Register (?<reg>[[:alpha:]]): (?<val>[0-9]+)$").unwrap();
89+
let prog_format = Regex::new(r"^Program: (?<insns>[,0-9]+)$").unwrap();
90+
91+
let mut cpu = CPU::new();
92+
93+
let mut lines: VecDeque<&str> = VecDeque::from_iter(input.lines());
94+
loop {
95+
let line = lines.pop_front()
96+
.unwrap()
97+
.trim();
98+
if line.is_empty() { break; }
99+
let caps = reg_format.captures(line).unwrap();
100+
cpu.load_reg(&caps["reg"].to_lowercase().chars().nth(0).unwrap(),
101+
(&caps["val"]).parse::<u32>().unwrap());
102+
}
103+
let line = lines.pop_front().unwrap().trim();
104+
let caps = prog_format.captures(line).unwrap();
105+
cpu.load_program((&caps["insns"])
106+
.split(",")
107+
.map(|i| i.parse::<u32>().unwrap())
108+
.collect());
109+
110+
while cpu.step() {}
111+
println!("{}", cpu.output.iter().map(|o| o.to_string()).collect::<Vec<_>>().join(","));
112+
}

0 commit comments

Comments
 (0)