main.rs
1 use std::{ 2 thread::{self, sleep}, 3 time::Duration, 4 }; 5 6 #[derive(Debug)] 7 pub struct Computer { 8 pub reg_a: u128, 9 pub reg_b: u128, 10 pub reg_c: u128, 11 pub ip: i128, 12 pub output: Vec<u8>, 13 } 14 15 impl Computer { 16 fn end(&self) -> String { 17 return format!( 18 "{}", 19 self.output 20 .iter() 21 .map(|n| n.to_string()) 22 .collect::<Vec<String>>() 23 .join(",") 24 ); 25 } 26 27 fn adv(&mut self, val: u128) { 28 self.reg_a /= 2u128.pow(val as u32); 29 } 30 31 fn bxl(&mut self, val: u128) { 32 self.reg_b ^= val; 33 } 34 35 fn bst(&mut self, val: u128) { 36 self.reg_b = val % 8; 37 } 38 39 fn jnz(&mut self, val: u128) { 40 if self.reg_a != 0 { 41 self.ip = val as i128 - 2; 42 } 43 } 44 45 fn bxc(&mut self, _val: u128) { 46 self.reg_b ^= self.reg_c; 47 } 48 49 fn out(&mut self, val: u128) { 50 self.output.push((val % 8) as u8); 51 } 52 53 fn bdv(&mut self, val: u128) { 54 self.reg_b = self.reg_a / 2u128.pow(val as u32); 55 } 56 57 fn cdv(&mut self, val: u128) { 58 self.reg_c = self.reg_a / 2u128.pow(val as u32); 59 } 60 61 fn exec(&mut self, i: u8, val: u128) { 62 let real_val: u128; 63 if [0, 2, 5, 6, 7].contains(&i) { 64 match val { 65 0 | 1 | 2 | 3 => real_val = val, 66 4 => real_val = self.reg_a, 67 5 => real_val = self.reg_b, 68 6 => real_val = self.reg_c, 69 _ => todo!(), 70 } 71 } else { 72 real_val = val; 73 } 74 match i { 75 0 => self.adv(real_val), 76 1 => self.bxl(real_val), 77 2 => self.bst(real_val), 78 3 => self.jnz(real_val), 79 4 => self.bxc(real_val), 80 5 => self.out(real_val), 81 6 => self.bdv(real_val), 82 7 => self.cdv(real_val), 83 _ => todo!(), 84 } 85 } 86 } 87 88 fn main() { 89 let input: Vec<&str> = std::str::from_utf8(include_bytes!("input")) 90 .unwrap() 91 .split("\n\n") 92 .collect(); 93 let registers: Vec<u128> = input[0] 94 .lines() 95 .map(|l| l.split(" ").last().unwrap().parse::<u128>().unwrap()) 96 .collect(); 97 let instructions: Vec<u8> = input[1] 98 .trim() 99 .split(" ") 100 .last() 101 .unwrap() 102 .split(",") 103 .map(|i| i.parse::<u8>().unwrap()) 104 .collect(); 105 106 let mut computer = Computer { 107 reg_a: registers[0], 108 reg_b: registers[1], 109 reg_c: registers[2], 110 ip: 0, 111 output: vec![], 112 }; 113 while (computer.ip as usize) < instructions.len() { 114 computer.exec( 115 instructions[computer.ip as usize], 116 instructions[computer.ip as usize + 1] as u128, 117 ); 118 computer.ip += 2; 119 if (computer.ip as usize) >= instructions.len() { 120 break; 121 } 122 } 123 println!("Part 1: {}", computer.end()); 124 125 // Part 2 (ONLY WORKS FOR MY INPUT) 126 let mut threads: Vec<thread::JoinHandle<()>> = vec![]; 127 for _i in 0..8 { 128 let input: Vec<&str> = std::str::from_utf8(include_bytes!("input")) 129 .unwrap() 130 .split("\n\n") 131 .collect(); 132 let registers: Vec<u128> = input[0] 133 .lines() 134 .map(|l| l.split(" ").last().unwrap().parse::<u128>().unwrap()) 135 .collect(); 136 let instructions: Vec<u8> = input[1] 137 .trim() 138 .split(" ") 139 .last() 140 .unwrap() 141 .split(",") 142 .map(|i| i.parse::<u8>().unwrap()) 143 .collect(); 144 let b = registers[1]; 145 let c = registers[2]; 146 threads.push(thread::spawn(move || { 147 let mut __i = _i; 148 let result = 'new_i: loop { 149 __i += 8; 150 let i = 7 + (1 + (0 + (6 + (3 + (2 + __i * 8) * 8) * 8) * 8) * 8) * 8; 151 let mut computer = Computer { 152 reg_a: i, 153 reg_b: b, 154 reg_c: c, 155 ip: 0, 156 output: vec![], 157 }; 158 while (computer.ip as usize) < instructions.len() { 159 computer.exec( 160 instructions[computer.ip as usize], 161 instructions[computer.ip as usize + 1] as u128, 162 ); 163 computer.ip += 2; 164 if (computer.ip as usize) >= instructions.len() { 165 break; 166 } 167 for (index, n) in computer.output.iter().enumerate() { 168 if instructions[index] != *n { 169 continue 'new_i; 170 } 171 } 172 if computer.output.len() > instructions.len() { 173 continue 'new_i; 174 } 175 } 176 if computer.output == instructions { 177 break i; 178 } 179 }; 180 println!("Part 2: {result}"); 181 })); 182 } 183 loop { 184 sleep(Duration::from_secs(1)); 185 } 186 }