From 169dba9b00ac8a8f3097164eafe5a69592180ec5 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Sun, 15 Dec 2019 21:52:18 -0800 Subject: [PATCH] Day 5, Part 1 --- inputs/day5 | 1 + src/machine.rs | 117 ++++++++++++++++++++++++++++++++----------------- src/main.rs | 25 +++++------ 3 files changed, 89 insertions(+), 54 deletions(-) create mode 100644 inputs/day5 diff --git a/inputs/day5 b/inputs/day5 new file mode 100644 index 0000000..04fe3ec --- /dev/null +++ b/inputs/day5 @@ -0,0 +1 @@ +3,225,1,225,6,6,1100,1,238,225,104,0,1001,210,88,224,101,-143,224,224,4,224,1002,223,8,223,101,3,224,224,1,223,224,223,101,42,92,224,101,-78,224,224,4,224,1002,223,8,223,1001,224,3,224,1,223,224,223,1101,73,10,225,1102,38,21,225,1102,62,32,225,1,218,61,224,1001,224,-132,224,4,224,102,8,223,223,1001,224,5,224,1,224,223,223,1102,19,36,225,102,79,65,224,101,-4898,224,224,4,224,102,8,223,223,101,4,224,224,1,224,223,223,1101,66,56,224,1001,224,-122,224,4,224,102,8,223,223,1001,224,2,224,1,224,223,223,1002,58,82,224,101,-820,224,224,4,224,1002,223,8,223,101,3,224,224,1,223,224,223,2,206,214,224,1001,224,-648,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,1102,76,56,224,1001,224,-4256,224,4,224,102,8,223,223,1001,224,6,224,1,223,224,223,1102,37,8,225,1101,82,55,225,1102,76,81,225,1101,10,94,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,8,226,677,224,102,2,223,223,1005,224,329,101,1,223,223,1008,677,677,224,1002,223,2,223,1006,224,344,1001,223,1,223,107,226,677,224,102,2,223,223,1005,224,359,1001,223,1,223,1108,677,677,224,1002,223,2,223,1006,224,374,101,1,223,223,1107,677,677,224,1002,223,2,223,1006,224,389,101,1,223,223,108,226,677,224,102,2,223,223,1006,224,404,101,1,223,223,7,677,677,224,102,2,223,223,1006,224,419,101,1,223,223,108,677,677,224,102,2,223,223,1006,224,434,1001,223,1,223,7,226,677,224,102,2,223,223,1006,224,449,1001,223,1,223,108,226,226,224,102,2,223,223,1005,224,464,101,1,223,223,8,226,226,224,1002,223,2,223,1006,224,479,101,1,223,223,1008,226,226,224,102,2,223,223,1005,224,494,1001,223,1,223,1008,677,226,224,1002,223,2,223,1005,224,509,101,1,223,223,7,677,226,224,102,2,223,223,1006,224,524,101,1,223,223,1007,677,226,224,1002,223,2,223,1006,224,539,1001,223,1,223,1108,677,226,224,102,2,223,223,1005,224,554,1001,223,1,223,8,677,226,224,1002,223,2,223,1005,224,569,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,584,101,1,223,223,1107,677,226,224,102,2,223,223,1006,224,599,101,1,223,223,107,226,226,224,102,2,223,223,1006,224,614,1001,223,1,223,107,677,677,224,1002,223,2,223,1005,224,629,1001,223,1,223,1107,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,659,1001,223,1,223,1007,226,226,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226 diff --git a/src/machine.rs b/src/machine.rs index 88aa289..77a97f0 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -1,41 +1,40 @@ use std::fs; +use std::iter::FromIterator; use std::str; +use std::sync::mpsc::{Sender, Receiver}; -const ADD: u64 = 1; -const MULTIPLY: u64 = 2; -const HALT: u64 = 99; +const ADD: i64 = 1; +const MULTIPLY: i64 = 2; +const INPUT: i64 = 3; +const OUTPUT: i64 = 4; +const HALT: i64 = 99; + +const MODE_POSITION: i64 = 0; +const MODE_IMMEDIATE: i64 = 1; #[derive(Clone, Debug, PartialEq)] pub struct Computer { - memory: Vec, + memory: Vec, position: usize } impl Computer { pub fn load(path: &str, position: usize) -> Computer { - let mut memory = vec![]; let byte_buffer = fs::read(path).unwrap(); let char_buffer = str::from_utf8(&byte_buffer).unwrap(); + Computer::from_string(&char_buffer, position) + } - let mut current = 0; - for c in char_buffer.chars() { - match c { - ',' => { - memory.push(current); - current = 0; - } - _ if c.is_digit(10) => { - let val = c.to_digit(10).unwrap() as u64; - current = (current * 10) + val; - } - _ if c.is_whitespace() => { - } - _ => { - panic!("Unrecognized character: '{}'", c); - } - } + fn from_string(char_buffer: &str, position: usize) -> Computer { + let mut memory = vec![]; + let mut char_iter = char_buffer.chars().peekable(); + + while char_iter.peek().is_some() { + let next_iter = char_iter.by_ref().take_while(|x| *x != ','); + let next_str = String::from_iter(next_iter); + let next = i64::from_str_radix(&next_str.trim(), 10).unwrap(); + memory.push(next); } - memory.push(current); Computer{ memory, position } } @@ -47,32 +46,57 @@ impl Computer { println!("POSITION: {}", self.position); } - pub fn read(&self, idx: usize) -> u64 { + pub fn read(&self, idx: usize) -> i64 { self.memory[idx] } - pub fn write(&mut self, idx: usize, val: u64) { + pub fn read_arg(&self, mode: i64, val: usize) -> i64 { + match mode { + MODE_POSITION => self.read(self.read(val) as usize), + MODE_IMMEDIATE => self.read(val), + _ => panic!("Unknown argument mode: {}", mode) + } + } + + pub fn write(&mut self, idx: usize, val: i64) { self.memory[idx] = val; } - fn step(&mut self) { - match self.read(self.position) { + fn step(&mut self, input: &Receiver, output: &Sender) { + let next_instruction = self.read(self.position); + let opcode = next_instruction % 100; + let arg1mode = (next_instruction / 100) % 10; + let arg2mode = (next_instruction / 1000) % 10; + let _arg3mode = (next_instruction / 10000) % 10; + + match opcode { ADD => { - let arg1 = self.read(self.position + 1) as usize; - let arg2 = self.read(self.position + 2) as usize; + let arg1 = self.read_arg(arg1mode, self.position + 1); + let arg2 = self.read_arg(arg2mode, self.position + 2); let dest = self.read(self.position + 3) as usize; - self.write(dest, self.read(arg1) + self.read(arg2)); + self.write(dest, arg1 + arg2); self.position += 4; } MULTIPLY => { - let arg1 = self.read(self.position + 1) as usize; - let arg2 = self.read(self.position + 2) as usize; + let arg1 = self.read_arg(arg1mode, self.position + 1); + let arg2 = self.read_arg(arg2mode, self.position + 2); let dest = self.read(self.position + 3) as usize; - self.write(dest, self.read(arg1) * self.read(arg2)); + self.write(dest, arg1 * arg2); self.position += 4; } + INPUT => { + let dest = self.read(self.position + 1) as usize; + let val = input.recv().expect("Failed to read input value from channel."); + self.write(dest, val); + self.position += 2; + } + OUTPUT => { + let arg1 = self.read_arg(arg1mode, self.position + 1); + output.send(arg1).expect("Send failed."); + self.position += 2; + } HALT => {} /* */ unknown_pos => @@ -84,36 +108,51 @@ impl Computer { self.read(self.position) == HALT } - pub fn run(&mut self) { + pub fn run(&mut self, input: &Receiver, output: &Sender) { while !self.halted() { - self.step(); + self.step(input, output); } } } +#[cfg(test)] +use std::sync::mpsc::channel; + #[test] fn test_examples() { + let (deadsend, deadrecv) = channel(); + let mut example1 = Computer{ memory: vec![1,0,0,0,99], position: 0 }; let answer1 = Computer{ memory: vec![2,0,0,0,99], position: 4 }; - example1.step(); + example1.step(&deadrecv, &deadsend); assert_eq!(example1, answer1); assert!(example1.halted()); let mut example2 = Computer{ memory: vec![2,3,0,3,99], position: 0 }; let answer2 = Computer{ memory: vec![2,3,0,6,99], position: 4 }; - example2.step(); + example2.step(&deadrecv, &deadsend); assert_eq!(example2, answer2); assert!(example2.halted()); let mut example3 = Computer{ memory: vec![2,4,4,5,99,0], position: 0 }; let answer3 = Computer{ memory: vec![2,4,4,5,99,9801], position: 4 }; - example3.step(); + example3.step(&deadrecv, &deadsend); assert_eq!(example3, answer3); assert!(example3.halted()); let mut example4 = Computer{ memory: vec![1,1,1,4,99,5,6,0,99], position: 0 }; let answer4 = Computer{ memory: vec![30,1,1,4,2,5,6,0,99], position: 8 }; - example4.run(); + example4.run(&deadrecv, &deadsend); assert_eq!(example4, answer4); assert!(example4.halted()); + + let mut example5 = Computer{ memory: vec![1002,4,3,4,33], position: 0 }; + let answer5 = Computer{ memory: vec![1002,4,3,4,99], position: 4 }; + example5.run(&deadrecv, &deadsend); + assert_eq!(example5, answer5); + + let mut example6 = Computer::from_string("1101,100,-1,4,0", 0); + let answer6 = Computer{ memory: vec![1101,100,-1,4,99], position: 4 }; + example6.run(&deadrecv, &deadsend); + assert_eq!(example6, answer6); } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ce859f8..34c4cb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use crate::args::Command; use crate::fuel::calculate_fuel; use crate::wiremap::WireMap; use std::cmp::{max,min}; +use std::sync::mpsc::channel; fn main() { match Command::get() { @@ -22,23 +23,17 @@ fn main() { println!("TOTAL FUEL: {}", total); } - Command::RunComputer(initial) => { + Command::RunComputer(mut initial) => { + let (my_sender, their_receiver) = channel(); + let (their_sender, my_receiver) = channel(); println!("Initial Computer:"); initial.show(); - println!("Searching ..."); - for noun in 0..99 { - for verb in 0..99 { - let mut proposed = initial.clone(); - proposed.write(1, noun); - proposed.write(2, verb); - proposed.run(); - if proposed.read(0) == 19690720 { - println!("Noun: {}", noun); - println!("Verb: {}", verb); - println!("ANSWER: {}", 100 * noun + verb); - break; - } - } + println!("Running, with input 1."); + my_sender.send(1).expect("Initial send failed"); + initial.run(&their_receiver, &their_sender); + let result = my_receiver.recv().expect("Didn't get initial result"); + for val in my_receiver.iter() { + println!("Received value: {}", val); } }