Add day 5 (again)

master
parent 8bd67f223a
commit 6c445ab130
  1. 1
      input/day5
  2. 10
      src/day5.rs
  3. 244
      src/intcode.rs

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1102,16,13,225,1001,88,68,224,101,-114,224,224,4,224,1002,223,8,223,1001,224,2,224,1,223,224,223,1101,8,76,224,101,-84,224,224,4,224,102,8,223,223,101,1,224,224,1,224,223,223,1101,63,58,225,1102,14,56,224,101,-784,224,224,4,224,102,8,223,223,101,4,224,224,1,223,224,223,1101,29,46,225,102,60,187,224,101,-2340,224,224,4,224,102,8,223,223,101,3,224,224,1,224,223,223,1102,60,53,225,1101,50,52,225,2,14,218,224,101,-975,224,224,4,224,102,8,223,223,1001,224,3,224,1,223,224,223,1002,213,79,224,101,-2291,224,224,4,224,102,8,223,223,1001,224,2,224,1,223,224,223,1,114,117,224,101,-103,224,224,4,224,1002,223,8,223,101,4,224,224,1,224,223,223,1101,39,47,225,101,71,61,224,101,-134,224,224,4,224,102,8,223,223,101,2,224,224,1,224,223,223,1102,29,13,225,1102,88,75,225,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1107,677,677,224,102,2,223,223,1006,224,329,1001,223,1,223,108,677,677,224,1002,223,2,223,1005,224,344,101,1,223,223,1008,226,226,224,102,2,223,223,1006,224,359,1001,223,1,223,1107,226,677,224,102,2,223,223,1006,224,374,1001,223,1,223,8,677,226,224,102,2,223,223,1006,224,389,101,1,223,223,8,226,226,224,102,2,223,223,1006,224,404,101,1,223,223,7,677,677,224,1002,223,2,223,1006,224,419,101,1,223,223,7,677,226,224,1002,223,2,223,1005,224,434,101,1,223,223,1108,677,226,224,1002,223,2,223,1006,224,449,1001,223,1,223,108,677,226,224,1002,223,2,223,1006,224,464,101,1,223,223,1108,226,677,224,1002,223,2,223,1006,224,479,101,1,223,223,1007,677,677,224,1002,223,2,223,1006,224,494,1001,223,1,223,107,226,226,224,102,2,223,223,1005,224,509,1001,223,1,223,1008,677,226,224,102,2,223,223,1005,224,524,1001,223,1,223,1007,226,226,224,102,2,223,223,1006,224,539,101,1,223,223,1108,677,677,224,102,2,223,223,1005,224,554,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,569,101,1,223,223,1107,677,226,224,1002,223,2,223,1006,224,584,1001,223,1,223,7,226,677,224,102,2,223,223,1005,224,599,101,1,223,223,108,226,226,224,1002,223,2,223,1005,224,614,101,1,223,223,107,226,677,224,1002,223,2,223,1005,224,629,1001,223,1,223,107,677,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,677,226,224,1002,223,2,223,1006,224,659,101,1,223,223,8,226,677,224,102,2,223,223,1005,224,674,1001,223,1,223,4,223,99,226

@ -0,0 +1,10 @@
use crate::intcode::IntCode;
use std::io::BufRead;
pub fn part1<F: BufRead> (mut input: F) {
let mut buf = String::new();
let _num_bytes = input.read_line(&mut buf).expect("Unable to first read line of input file");
let mut intcode = IntCode::from_str(&buf);
println!("Input value `1` for part 1 and `5` for part 2:");
let _res = intcode.run();
}

@ -0,0 +1,244 @@
pub struct IntCode {
addr_ptr: usize,
memory: Vec<isize>,
}
pub struct Value {
value: isize,
address: Option<usize>,
}
struct Op {
argc: u8,
argv: Vec<Value>,
function: OpCodeFn,
}
pub enum ResultAction {
None,
Terminate,
Write {
address: usize,
value: isize,
},
Jump {
address: usize,
}
}
enum ParamMode {
Position,
Imediate
}
type OpCodeFn = fn(&Vec<Value>) -> ResultAction;
impl ParamMode {
fn from_int(mode: usize) -> Self {
match mode {
0 => ParamMode::Position,
1 => ParamMode::Imediate,
_ => panic!("Unknown parameter mode {}", mode)
}
}
}
impl IntCode {
pub fn from_vec(v: Vec<isize>) -> Self {
IntCode {
memory: v,
addr_ptr: 0
}
}
pub fn from_str(s: &str) -> Self {
Self::from_vec(s.trim().split(",").filter_map(|n| n.parse().ok()).collect())
}
fn get_op_modes(&mut self) -> (u8, Vec<ParamMode>) {
let code = self.read_next();
let op = (code % 100) as u8;
let mut modes = code / 100;
let mut vmodes = Vec::new();
while modes > 0 {
vmodes.push(ParamMode::from_int(modes as usize % 10));
modes = modes / 10;
}
(op, vmodes)
}
fn read_next(&mut self) -> isize {
self.addr_ptr += 1;
self.memory[self.addr_ptr - 1]
}
fn read(&self, address: usize) -> isize {
self.memory[address]
}
fn write(&mut self, address: usize, value: isize) {
self.memory[address] = value;
}
fn jump(&mut self, address: usize) {
self.addr_ptr = address;
}
pub fn run(&mut self) -> isize {
loop {
let op = Op::from_intcode(self);
let res = op.run();
match res {
ResultAction::Write { address, value } => self.write(address, value),
ResultAction::Jump { address } => self.jump(address),
ResultAction::None => (),
ResultAction::Terminate => break,
}
}
self.read(0)
}
}
impl Op {
fn from_intcode(intcode: &mut IntCode) -> Self {
let (code, vmodes) = intcode.get_op_modes();
let mut op = Op::from_code(code);
for idx in 0..(op.argc) {
let code = intcode.read_next();
let arg = match vmodes.get(idx as usize).unwrap_or(&ParamMode::Position) {
ParamMode::Position => {
let value = intcode.read(code as usize);
Value { address: Some(code as usize), value }
},
ParamMode::Imediate => Value { address: None, value: code }
};
op.argv.push(arg);
}
op
}
fn from_code(code: u8) -> Self {
match code {
1 => Self::new(3, ops::add),
2 => Self::new(3, ops::mul),
3 => Self::new(1, ops::cin),
4 => Self::new(1, ops::cout),
5 => Self::new(2, ops::jump_if_true),
6 => Self::new(2, ops::jump_if_false),
7 => Self::new(3, ops::lt),
8 => Self::new(3, ops::eq),
99 => Self::new(0, ops::exit),
c => panic!("Unknown opcode {}", c)
}
}
fn new(argc: u8, function: OpCodeFn) -> Self {
Op {
argc,
argv: Vec::new(),
function,
}
}
fn run(&self) -> ResultAction {
(self.function)(&self.argv)
}
}
mod ops {
use super::{Value, ResultAction};
use std::io;
pub fn add(argv: &Vec<Value>) -> ResultAction {
ResultAction::Write {
address: argv[2].address.unwrap(),
value: (argv[0].value + argv[1].value) as isize
}
}
pub fn mul(argv: &Vec<Value>) -> ResultAction {
ResultAction::Write {
address: argv[2].address.unwrap(),
value: (argv[0].value * argv[1].value) as isize
}
}
pub fn exit(_argv: &Vec<Value>) -> ResultAction {
ResultAction::Terminate
}
pub fn cin(argv: &Vec<Value>) -> ResultAction {
let mut value = String::new();
let _ = io::stdin()
.read_line(&mut value)
.expect("Unable to read stdin");
ResultAction::Write {
address: argv[0].address.unwrap(),
value: value.trim().parse().unwrap(),
}
}
pub fn cout(argv: &Vec<Value>) -> ResultAction {
println!("{}", argv[0].value);
ResultAction::None
}
pub fn jump_if_true(argv: &Vec<Value>) -> ResultAction {
if argv[0].value != 0 {
ResultAction::Jump { address: argv[1].value as usize }
} else {
ResultAction::None
}
}
pub fn jump_if_false(argv: &Vec<Value>) -> ResultAction {
if argv[0].value == 0 {
ResultAction::Jump { address: argv[1].value as usize }
} else {
ResultAction::None
}
}
pub fn lt(argv: &Vec<Value>) -> ResultAction {
ResultAction::Write {
address: argv[2].address.unwrap(),
value: if argv[0].value < argv[1].value { 1 } else { 0 }
}
}
pub fn eq(argv: &Vec<Value>) -> ResultAction {
ResultAction::Write {
address: argv[2].address.unwrap(),
value: if argv[0].value == argv[1].value { 1 } else { 0 }
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_run_intcode_position_mode() {
let input1 = vec![1, 0, 0, 0, 99];
let input2 = vec![2, 0, 5, 0, 99, 3];
let mut intcode = IntCode::from_vec(input1);
assert_eq!(intcode.run(), 2);
intcode = IntCode::from_vec(input2);
assert_eq!(intcode.run(), 6);
}
#[test]
fn test_run_intcode_imediate_mode() {
let input = vec![1002, 4, 3, 4, 33];
let mut intcode = IntCode::from_vec(input);
intcode.run();
assert_eq!(99, intcode.memory[4]);
}
}
Loading…
Cancel
Save