--- /dev/null
+use std::error::Error;
+use std::path::Path;
+
+struct Computer {
+ regA: u64,
+ regB: u64,
+ regC: u64,
+ prgm: Vec<u8>,
+ ptr: usize,
+ out: Vec<u8>,
+}
+
+impl Computer {
+ pub fn new(input: &str) -> Self {
+ let (regs, mut prgm) = input.split_once("\n\n").unwrap();
+
+ let regs: Vec<u64> = regs.split("\n")
+ .map(|l| l[12..l.len()].parse::<u64>().unwrap())
+ .collect();
+ let regA = regs[0];
+ let regB = regs[1];
+ let regC = regs[2];
+
+ if prgm.ends_with("\n") {
+ prgm = &prgm[0..prgm.len()-1];
+ }
+
+ let prgm: Vec<u8> = prgm[9..prgm.len()].split(",")
+ .map(|v| v.parse::<u8>().unwrap())
+ .collect();
+ let ptr = 0;
+ let out = Vec::new();
+
+ Self { regA, regB, regC, prgm, ptr, out }
+ }
+
+ fn adv(&self, num: u64, operand: u8) -> u64 {
+ num / 2_u64.pow(self.combo(operand) as u32)
+ }
+
+ fn combo(&self, operand: u8) -> u64 {
+ match operand {
+ 0 | 1 | 2 | 3 => operand as u64,
+ 4 => self.regA,
+ 5 => self.regB,
+ 6 => self.regC,
+ _ => unreachable!(),
+ }
+ }
+
+ fn run(&mut self) {
+ while self.ptr < self.prgm.len() {
+ let opcode = self.prgm[self.ptr];
+ let operand = self.prgm[self.ptr + 1];
+ match opcode {
+ 0 => self.regA = self.adv(self.regA, operand),
+ 1 => self.regB ^= operand as u64,
+ 2 => self.regB = self.combo(operand) % 8,
+ 3 => {
+ if self.regA != 0 {
+ self.ptr = operand as usize;
+ continue;
+ }
+ },
+ 4 => self.regB ^= self.regC,
+ 5 => self.out.push((self.combo(operand) % 8) as u8),
+ 6 => self.regB = self.adv(self.regA, operand),
+ 7 => self.regC = self.adv(self.regA, operand),
+ _ => {}
+ }
+ self.ptr += 2;
+ }
+ //println!("regA={} regB={} regC={} {:?}", self.regA, self.regB, self.regC, self.out);
+ }
+
+ fn print(&self) -> String {
+ let s: Vec<String> = self.out.iter()
+ .map(|v| v.to_string())
+ .collect();
+ s.join(",")
+ }
+}
+
+fn run_part1(input: &str) -> Result<String, Box<dyn Error>> {
+ println!("Running {} - part 1", get_day());
+
+ let mut computer = Computer::new(input);
+ computer.run();
+ Ok(computer.print())
+}
+
+fn run_part2(input: &str) -> Result<String, Box<dyn Error>> {
+ println!("Running {} - part 2", get_day());
+
+ let res = "".to_string();
+ Ok(res)
+}
+
+pub fn run(input: &str) -> Result<(), Box<dyn Error>> {
+ let res = run_part1(input)?;
+ println!("{res}");
+
+ let res = run_part2(input)?;
+ println!("{res}");
+
+ Ok(())
+}
+
+fn get_day() -> String {
+ let filename = file!();
+ Path::new(filename).file_stem().unwrap().to_str().unwrap().to_string()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ static TEXT_INPUT_0: &str = "\
+Register A: 0
+Register B: 0
+Register C: 9
+
+Program: 2,6";
+ static TEXT_INPUT_1: &str = "\
+Register A: 10
+Register B: 0
+Register C: 0
+
+Program: 5,0,5,1,5,4";
+ static TEXT_INPUT_2: &str = "\
+Register A: 2024
+Register B: 0
+Register C: 0
+
+Program: 0,1,5,4,3,0";
+ static TEXT_INPUT_3: &str = "\
+Register A: 0
+Register B: 29
+Register C: 0
+
+Program: 1,7";
+ static TEXT_INPUT_4: &str = "\
+Register A: 0
+Register B: 2024
+Register C: 43690
+
+Program: 4,0";
+ static TEXT_INPUT_5: &str = "\
+Register A: 729
+Register B: 0
+Register C: 0
+
+Program: 0,1,5,4,3,0";
+
+ #[test]
+ fn test_part1() {
+ assert_eq!("", run_part1(TEXT_INPUT_0).unwrap());
+ assert_eq!("0,1,2", run_part1(TEXT_INPUT_1).unwrap());
+ assert_eq!("4,2,5,6,7,7,7,7,3,1,0", run_part1(TEXT_INPUT_2).unwrap());
+ assert_eq!("", run_part1(TEXT_INPUT_3).unwrap());
+ assert_eq!("", run_part1(TEXT_INPUT_4).unwrap());
+ assert_eq!("4,6,3,5,6,3,5,2,1,0", run_part1(TEXT_INPUT_5).unwrap());
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!("", run_part2(TEXT_INPUT_5).unwrap());
+ }
+}