Skip to content

Instantly share code, notes, and snippets.

@winstonewert
Created December 19, 2018 07:10
Show Gist options
  • Save winstonewert/9e77334388c9dec9d581805dfc7e7814 to your computer and use it in GitHub Desktop.
Save winstonewert/9e77334388c9dec9d581805dfc7e7814 to your computer and use it in GitHub Desktop.
#![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(&registers, instruction.mode_a, instruction.a);
let value_b = resolve(&registers, 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