Day 5, Part 1
This commit is contained in:
1
inputs/day5
Normal file
1
inputs/day5
Normal file
@@ -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
|
||||||
117
src/machine.rs
117
src/machine.rs
@@ -1,41 +1,40 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::iter::FromIterator;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::sync::mpsc::{Sender, Receiver};
|
||||||
|
|
||||||
const ADD: u64 = 1;
|
const ADD: i64 = 1;
|
||||||
const MULTIPLY: u64 = 2;
|
const MULTIPLY: i64 = 2;
|
||||||
const HALT: u64 = 99;
|
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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Computer {
|
pub struct Computer {
|
||||||
memory: Vec<u64>,
|
memory: Vec<i64>,
|
||||||
position: usize
|
position: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Computer {
|
impl Computer {
|
||||||
pub fn load(path: &str, position: usize) -> Computer {
|
pub fn load(path: &str, position: usize) -> Computer {
|
||||||
let mut memory = vec![];
|
|
||||||
let byte_buffer = fs::read(path).unwrap();
|
let byte_buffer = fs::read(path).unwrap();
|
||||||
let char_buffer = str::from_utf8(&byte_buffer).unwrap();
|
let char_buffer = str::from_utf8(&byte_buffer).unwrap();
|
||||||
|
Computer::from_string(&char_buffer, position)
|
||||||
|
}
|
||||||
|
|
||||||
let mut current = 0;
|
fn from_string(char_buffer: &str, position: usize) -> Computer {
|
||||||
for c in char_buffer.chars() {
|
let mut memory = vec![];
|
||||||
match c {
|
let mut char_iter = char_buffer.chars().peekable();
|
||||||
',' => {
|
|
||||||
memory.push(current);
|
while char_iter.peek().is_some() {
|
||||||
current = 0;
|
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);
|
||||||
}
|
}
|
||||||
_ 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memory.push(current);
|
|
||||||
|
|
||||||
Computer{ memory, position }
|
Computer{ memory, position }
|
||||||
}
|
}
|
||||||
@@ -47,32 +46,57 @@ impl Computer {
|
|||||||
println!("POSITION: {}", self.position);
|
println!("POSITION: {}", self.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self, idx: usize) -> u64 {
|
pub fn read(&self, idx: usize) -> i64 {
|
||||||
self.memory[idx]
|
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;
|
self.memory[idx] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self) {
|
fn step(&mut self, input: &Receiver<i64>, output: &Sender<i64>) {
|
||||||
match self.read(self.position) {
|
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 => {
|
ADD => {
|
||||||
let arg1 = self.read(self.position + 1) as usize;
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read(self.position + 2) as usize;
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
let dest = self.read(self.position + 3) as usize;
|
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;
|
self.position += 4;
|
||||||
}
|
}
|
||||||
MULTIPLY => {
|
MULTIPLY => {
|
||||||
let arg1 = self.read(self.position + 1) as usize;
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read(self.position + 2) as usize;
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
let dest = self.read(self.position + 3) as usize;
|
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;
|
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 => {}
|
HALT => {}
|
||||||
/* */
|
/* */
|
||||||
unknown_pos =>
|
unknown_pos =>
|
||||||
@@ -84,36 +108,51 @@ impl Computer {
|
|||||||
self.read(self.position) == HALT
|
self.read(self.position) == HALT
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self, input: &Receiver<i64>, output: &Sender<i64>) {
|
||||||
while !self.halted() {
|
while !self.halted() {
|
||||||
self.step();
|
self.step(input, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
|
let (deadsend, deadrecv) = channel();
|
||||||
|
|
||||||
let mut example1 = Computer{ memory: vec![1,0,0,0,99], position: 0 };
|
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 };
|
let answer1 = Computer{ memory: vec![2,0,0,0,99], position: 4 };
|
||||||
example1.step();
|
example1.step(&deadrecv, &deadsend);
|
||||||
assert_eq!(example1, answer1);
|
assert_eq!(example1, answer1);
|
||||||
assert!(example1.halted());
|
assert!(example1.halted());
|
||||||
|
|
||||||
let mut example2 = Computer{ memory: vec![2,3,0,3,99], position: 0 };
|
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 };
|
let answer2 = Computer{ memory: vec![2,3,0,6,99], position: 4 };
|
||||||
example2.step();
|
example2.step(&deadrecv, &deadsend);
|
||||||
assert_eq!(example2, answer2);
|
assert_eq!(example2, answer2);
|
||||||
assert!(example2.halted());
|
assert!(example2.halted());
|
||||||
|
|
||||||
let mut example3 = Computer{ memory: vec![2,4,4,5,99,0], position: 0 };
|
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 };
|
let answer3 = Computer{ memory: vec![2,4,4,5,99,9801], position: 4 };
|
||||||
example3.step();
|
example3.step(&deadrecv, &deadsend);
|
||||||
assert_eq!(example3, answer3);
|
assert_eq!(example3, answer3);
|
||||||
assert!(example3.halted());
|
assert!(example3.halted());
|
||||||
|
|
||||||
let mut example4 = Computer{ memory: vec![1,1,1,4,99,5,6,0,99], position: 0 };
|
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 };
|
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_eq!(example4, answer4);
|
||||||
assert!(example4.halted());
|
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);
|
||||||
}
|
}
|
||||||
25
src/main.rs
25
src/main.rs
@@ -7,6 +7,7 @@ use crate::args::Command;
|
|||||||
use crate::fuel::calculate_fuel;
|
use crate::fuel::calculate_fuel;
|
||||||
use crate::wiremap::WireMap;
|
use crate::wiremap::WireMap;
|
||||||
use std::cmp::{max,min};
|
use std::cmp::{max,min};
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match Command::get() {
|
match Command::get() {
|
||||||
@@ -22,23 +23,17 @@ fn main() {
|
|||||||
println!("TOTAL FUEL: {}", total);
|
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:");
|
println!("Initial Computer:");
|
||||||
initial.show();
|
initial.show();
|
||||||
println!("Searching ...");
|
println!("Running, with input 1.");
|
||||||
for noun in 0..99 {
|
my_sender.send(1).expect("Initial send failed");
|
||||||
for verb in 0..99 {
|
initial.run(&their_receiver, &their_sender);
|
||||||
let mut proposed = initial.clone();
|
let result = my_receiver.recv().expect("Didn't get initial result");
|
||||||
proposed.write(1, noun);
|
for val in my_receiver.iter() {
|
||||||
proposed.write(2, verb);
|
println!("Received value: {}", val);
|
||||||
proposed.run();
|
|
||||||
if proposed.read(0) == 19690720 {
|
|
||||||
println!("Noun: {}", noun);
|
|
||||||
println!("Verb: {}", verb);
|
|
||||||
println!("ANSWER: {}", 100 * noun + verb);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user