day 19 part 1
parent
c82b633b65
commit
0fff0ac276
|
@ -0,0 +1,4 @@
|
||||||
|
[[package]]
|
||||||
|
name = "day19"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "day19"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Andrew Coleman <penguincoder@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -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
|
|
@ -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<Opcode>,
|
||||||
|
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::<usize>().unwrap(),
|
||||||
|
iter.nth(0).unwrap().parse::<usize>().unwrap(),
|
||||||
|
iter.nth(0).unwrap().parse::<usize>().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::<usize>()
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
Loading…
Reference in New Issue