Files
adventofcode/2018/src/day19.rs

93 lines
2.4 KiB
Rust

use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;
use common::Solution;
use cpu::OpCode;
use cpu::CPU;
#[derive(Default)]
pub struct Day19 {
program: Vec<(OpCode, [i32; 3])>,
ip: usize,
}
impl Day19 {
pub fn new() -> Self {
Default::default()
}
fn read_input(&mut self, input: &mut dyn Read) {
let reader = BufReader::new(input);
for line in reader.lines() {
let line = line.unwrap();
if line.starts_with('#') {
self.ip = line.split(' ').last().unwrap().parse().unwrap();
} else {
let mut parts = line.split(' ');
let opcode = OpCode::from(parts.next().unwrap());
let mut operands = [0; 3];
for (target, part) in operands.iter_mut().zip(parts) {
*target = part.parse().unwrap();
}
self.program.push((opcode, operands));
}
}
}
}
impl Solution for Day19 {
fn part1(&mut self, input: &mut dyn Read) -> String {
self.read_input(input);
let mut cpu = CPU::new();
while (cpu.registers[self.ip] as usize) < self.program.len() {
let (opcode, operands) = &self.program[cpu.registers[self.ip] as usize];
cpu.execute(*opcode, operands).unwrap();
cpu.registers[self.ip] += 1;
}
cpu.registers[0].to_string()
}
fn part2(&mut self, input: &mut dyn Read) -> String {
self.read_input(input);
let mut cpu = CPU::new();
cpu.registers[0] = 1;
// This is optimized for my input.
assert_eq!(self.ip, 3);
while (cpu.registers[3] as usize) < self.program.len() {
if cpu.registers[3] == 1 {
let reg = &mut cpu.registers;
reg[0] = (1..=reg[5]).filter(|&x| reg[5] % x == 0).sum();
reg[3] = 16;
}
let (opcode, operands) = &self.program[cpu.registers[self.ip] as usize];
cpu.execute(*opcode, operands).unwrap();
cpu.registers[self.ip] += 1;
}
cpu.registers[0].to_string()
}
}
#[cfg(test)]
mod tests {
use common::Solution;
use day19::Day19;
const SAMPLE_INPUT: &[u8] = include_bytes!("samples/19.txt");
#[test]
fn sample_part1() {
let mut instance = Day19::new();
assert_eq!("7", instance.part1(&mut SAMPLE_INPUT));
}
}