Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![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());
- }
Add Comment
Please, Sign In to add comment