Created
December 19, 2018 07:10
-
-
Save winstonewert/9e77334388c9dec9d581805dfc7e7814 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(unused_imports)] | |
extern crate regex; | |
#[macro_use] | |
extern crate lazy_static; | |
extern crate itertools; | |
extern crate pbr; | |
extern crate colored; | |
use std::collections::VecDeque; | |
use itertools::Itertools; | |
use pbr::ProgressBar; | |
use regex::Regex; | |
use std::collections::HashMap; | |
use std::collections::HashSet; | |
use std::fs::File; | |
use std::io::Read; | |
use colored::*; | |
#[derive(Debug, Copy, Clone)] | |
enum OpType { | |
add, | |
set, | |
mul, | |
ban, | |
bor, | |
gt, | |
eq | |
} | |
#[derive(Debug, Copy, Clone)] | |
enum Mode { | |
Value, | |
Register | |
} | |
#[derive(Debug, Copy, Clone)] | |
struct Instruction { | |
op: OpType, | |
mode_a: Mode, | |
mode_b: Mode, | |
a: i32, | |
b: i32, | |
c: i32 | |
} | |
#[derive(Debug)] | |
struct Program { | |
ip_register: usize, | |
instructions: Vec<Instruction> | |
} | |
fn resolve(registers: &[i32], mode: Mode, value: i32) -> i32 { | |
match mode { | |
Mode::Value => value, | |
Mode::Register => registers[value as usize] | |
} | |
} | |
impl Program { | |
fn execute(&self) -> i32 { | |
let mut registers = vec![0i32; 6]; | |
registers[0] = 1; | |
let mut ip = 0; | |
loop { | |
registers[self.ip_register] = ip; | |
if ip == 2 && registers[3] != 0 { | |
if registers[5] % registers[3] == 0 { | |
registers[0] += registers[3]; | |
} | |
registers[2] = 0; | |
registers[1] = registers[5]; | |
ip = 12; | |
continue; | |
} | |
if ip as usize >= self.instructions.len() { | |
break; | |
} | |
let instruction = self.instructions[ip as usize]; | |
println!("{} {:?} {:?}", ip, registers, instruction); | |
let value_a = resolve(®isters, instruction.mode_a, instruction.a); | |
let value_b = resolve(®isters, instruction.mode_b, instruction.b); | |
let result = match instruction.op { | |
OpType::add => value_a + value_b, | |
OpType::mul => value_a * value_b, | |
OpType::ban => value_a & value_b, | |
OpType::bor => value_a | value_b, | |
OpType::gt => (value_a > value_b) as i32, | |
OpType::eq => (value_a == value_b) as i32, | |
OpType::set => value_a | |
}; | |
registers[instruction.c as usize] = result; | |
ip = registers[self.ip_register]; | |
ip += 1; | |
} | |
registers[0] | |
} | |
} | |
fn parse_op(op: &str) -> (OpType, Mode, Mode) { | |
match op { | |
"addr" => (OpType::add, Mode::Register, Mode::Register), | |
"addi" => (OpType::add, Mode::Register, Mode::Value), | |
"mulr" => (OpType::mul, Mode::Register, Mode::Register), | |
"muli" => (OpType::mul, Mode::Register, Mode::Value), | |
"banr" => (OpType::ban, Mode::Register, Mode::Register), | |
"bani" => (OpType::ban, Mode::Register, Mode::Value), | |
"borr" => (OpType::bor, Mode::Register, Mode::Register), | |
"bori" => (OpType::bor, Mode::Register, Mode::Value), | |
"setr" => (OpType::set, Mode::Register, Mode::Value), | |
"seti" => (OpType::set, Mode::Value, Mode::Value), | |
"gtir" => (OpType::gt, Mode::Value, Mode::Register), | |
"gtri" => (OpType::gt, Mode::Register, Mode::Value), | |
"gtrr" => (OpType::gt, Mode::Register, Mode::Register), | |
"eqir" => (OpType::eq, Mode::Value, Mode::Register), | |
"eqri" => (OpType::eq, Mode::Register, Mode::Value), | |
"eqrr" => (OpType::eq, Mode::Register, Mode::Register), | |
_ => panic!("{}", op) | |
} | |
} | |
fn parse(text: &str) -> Program { | |
let mut lines = text.lines(); | |
let ip_line = lines.next().unwrap(); | |
assert!(ip_line.starts_with("#ip")); | |
let ip_register: usize = ip_line.split_whitespace().collect_vec()[1].parse().unwrap(); | |
let instructions = lines.map(|line| { | |
let parts = line.split_whitespace().collect_vec(); | |
let (op, mode_a, mode_b) = parse_op(parts[0]); | |
Instruction { | |
op,mode_a,mode_b, a: parts[1].parse().unwrap(), | |
b: parts[2].parse().unwrap(), | |
c: parts[3].parse().unwrap() | |
} | |
}).collect(); | |
Program {ip_register,instructions} | |
} | |
mod test { | |
use super::*; | |
#[test] | |
fn test_it() { | |
let text= "#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"; | |
let program = parse(text); | |
assert_eq!(program.execute(), 7); | |
} | |
} | |
fn main() { | |
let text = include_str!("input.txt"); | |
let program = parse(text); | |
println!("{}", program.execute()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment