diff --git a/2018/day19/Cargo.lock b/2018/day19/Cargo.lock new file mode 100644 index 0000000..d8c290d --- /dev/null +++ b/2018/day19/Cargo.lock @@ -0,0 +1,4 @@ +[[package]] +name = "day19" +version = "0.1.0" + diff --git a/2018/day19/Cargo.toml b/2018/day19/Cargo.toml new file mode 100644 index 0000000..4cd6ec4 --- /dev/null +++ b/2018/day19/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day19" +version = "0.1.0" +authors = ["Andrew Coleman "] +edition = "2018" + +[dependencies] diff --git a/2018/day19/input b/2018/day19/input new file mode 100644 index 0000000..a3ba0ea --- /dev/null +++ b/2018/day19/input @@ -0,0 +1,37 @@ +#ip 3 +addi 3 16 3 +seti 1 8 4 +seti 1 4 5 +mulr 4 5 1 +eqrr 1 2 1 +addr 1 3 3 +addi 3 1 3 +addr 4 0 0 +addi 5 1 5 +gtrr 5 2 1 +addr 3 1 3 +seti 2 1 3 +addi 4 1 4 +gtrr 4 2 1 +addr 1 3 3 +seti 1 3 3 +mulr 3 3 3 +addi 2 2 2 +mulr 2 2 2 +mulr 3 2 2 +muli 2 11 2 +addi 1 3 1 +mulr 1 3 1 +addi 1 17 1 +addr 2 1 2 +addr 3 0 3 +seti 0 3 3 +setr 3 0 1 +mulr 1 3 1 +addr 3 1 1 +mulr 3 1 1 +muli 1 14 1 +mulr 1 3 1 +addr 2 1 2 +seti 0 8 0 +seti 0 9 3 diff --git a/2018/day19/src/main.rs b/2018/day19/src/main.rs new file mode 100644 index 0000000..2bac3ba --- /dev/null +++ b/2018/day19/src/main.rs @@ -0,0 +1,245 @@ +use std::fs::File; +use std::io::{BufRead, BufReader}; + +type Registers = [usize; 6]; + +#[derive(Debug)] +struct Opcode { + cmd: String, + args: OpcodeArgs, +} + +type OpcodeArgs = [usize; 3]; + +struct Program { + registers: Registers, + instructions: Vec, + ip: usize, +} + +fn iter_to_opcode(iter: &mut std::str::SplitWhitespace) -> Opcode { + Opcode { + cmd: iter.nth(0).unwrap().to_string(), + args: [ + iter.nth(0).unwrap().parse::().unwrap(), + iter.nth(0).unwrap().parse::().unwrap(), + iter.nth(0).unwrap().parse::().unwrap(), + ], + } +} + +fn read_program_from_file(filename: &str) -> Program { + let mut lines = BufReader::new(File::open(filename).unwrap()).lines(); + let ip = lines.nth(0).unwrap(); + let instructions = lines + .map(|line| iter_to_opcode(&mut line.unwrap().split_whitespace())) + .collect(); + Program { + registers: [0usize; 6], + instructions, + ip: ip + .unwrap() + .split_whitespace() + .nth(1) + .unwrap() + .parse::() + .unwrap(), + } +} + +fn addr(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] + input_registers[args[1]]; + //dbg!(output_registers); + output_registers +} + +fn addi(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] + args[1]; + //dbg!(output_registers); + output_registers +} + +fn mulr(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] * input_registers[args[1]]; + //dbg!(output_registers); + output_registers +} + +fn muli(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] * args[1]; + //dbg!(output_registers); + output_registers +} + +fn banr(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] & input_registers[args[1]]; + //dbg!(output_registers); + output_registers +} + +fn bani(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] & args[1]; + //dbg!(output_registers); + output_registers +} + +fn borr(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] | input_registers[args[1]]; + //dbg!(output_registers); + output_registers +} + +fn bori(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]] | args[1]; + //dbg!(output_registers); + output_registers +} + +fn setr(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = input_registers[args[0]]; + //dbg!(output_registers); + output_registers +} + +fn seti(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + output_registers[args[2]] = args[0]; + //dbg!(output_registers); + output_registers +} + +fn gtir(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + if args[0] > input_registers[args[1]] { + output_registers[args[2]] = 1; + } else { + output_registers[args[2]] = 0; + } + //dbg!(output_registers); + output_registers +} + +fn gtri(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + if input_registers[args[0]] > args[1] { + output_registers[args[2]] = 1; + } else { + output_registers[args[2]] = 0; + } + //dbg!(output_registers); + output_registers +} + +fn gtrr(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + if input_registers[args[0]] > input_registers[args[1]] { + output_registers[args[2]] = 1; + } else { + output_registers[args[2]] = 0; + } + //dbg!(output_registers); + output_registers +} + +fn eqir(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + if args[0] == input_registers[args[1]] { + output_registers[args[2]] = 1; + } else { + output_registers[args[2]] = 0; + } + //dbg!(output_registers); + output_registers +} + +fn eqri(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + if input_registers[args[0]] == args[1] { + output_registers[args[2]] = 1; + } else { + output_registers[args[2]] = 0; + } + //dbg!(output_registers); + output_registers +} + +fn eqrr(input_registers: Registers, args: OpcodeArgs) -> Registers { + let mut output_registers = input_registers.clone(); + if input_registers[args[0]] == input_registers[args[1]] { + output_registers[args[2]] = 1; + } else { + output_registers[args[2]] = 0; + } + //dbg!(output_registers); + output_registers +} + +fn execute_program(program: &mut Program) { + while let Some(op) = program.instructions.get(program.registers[program.ip]) { + //dbg!(op); + let output_registers = match op.cmd.as_str() { + "addr" => addr(program.registers, op.args), + "addi" => addi(program.registers, op.args), + "mulr" => mulr(program.registers, op.args), + "muli" => muli(program.registers, op.args), + "banr" => banr(program.registers, op.args), + "bani" => bani(program.registers, op.args), + "borr" => borr(program.registers, op.args), + "bori" => bori(program.registers, op.args), + "setr" => setr(program.registers, op.args), + "seti" => seti(program.registers, op.args), + "gtir" => gtir(program.registers, op.args), + "gtri" => gtri(program.registers, op.args), + "gtrr" => gtrr(program.registers, op.args), + "eqir" => eqir(program.registers, op.args), + "eqri" => eqri(program.registers, op.args), + "eqrr" => eqrr(program.registers, op.args), + _ => panic!("No decoded instruction available for {}", op.cmd), + }; + program.registers[0] = output_registers[0]; + program.registers[1] = output_registers[1]; + program.registers[2] = output_registers[2]; + program.registers[3] = output_registers[3]; + program.registers[4] = output_registers[4]; + program.registers[5] = output_registers[5]; + program.registers[program.ip] += 1; + } + program.registers[program.ip] -= 1; +} + +fn main() { + let mut program = read_program_from_file("input"); + execute_program(&mut program); + println!("final value of register 0: {:?}", program.registers[0]); + let mut program2 = read_program_from_file("input"); + program2.registers[0] = 1; + execute_program(&mut program2); + println!("final value of register 0 with modified start value {}", program2.registers[0]); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sample_one() { + let mut program = read_program_from_file("test-input"); + execute_program(&mut program); + let output_registers = program.registers; + assert_eq!(output_registers[0], 6); + assert_eq!(output_registers[1], 5); + assert_eq!(output_registers[2], 6); + assert_eq!(output_registers[3], 0); + assert_eq!(output_registers[4], 0); + assert_eq!(output_registers[5], 9); + } +} diff --git a/2018/day19/test-input b/2018/day19/test-input new file mode 100644 index 0000000..d7d2a21 --- /dev/null +++ b/2018/day19/test-input @@ -0,0 +1,8 @@ +#ip 0 +seti 5 0 1 +seti 6 0 2 +addi 0 1 0 +addr 1 2 3 +setr 1 0 0 +seti 8 0 4 +seti 9 0 5