Fix channels (so they end), and finish day 5.
This commit is contained in:
54
src/endchannel.rs
Normal file
54
src/endchannel.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
pub struct Sender<T> {
|
||||||
|
underlying: mpsc::Sender<Option<T>>,
|
||||||
|
done: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Sender<T> {
|
||||||
|
pub fn send(&self, t: T) {
|
||||||
|
if self.done {
|
||||||
|
panic!("Sending on previously-closed channel.");
|
||||||
|
}
|
||||||
|
self.underlying.send(Some(t)).expect("Channel mysteriously closed on send.");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn conclude(&mut self) {
|
||||||
|
self.underlying.send(None).expect("Failed to close channel.");
|
||||||
|
self.done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Receiver<T> {
|
||||||
|
underlying: mpsc::Receiver<Option<T>>,
|
||||||
|
done: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Receiver<T> {
|
||||||
|
pub fn recv(&mut self) -> Option<T> {
|
||||||
|
if self.done {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.underlying.recv() {
|
||||||
|
Err(e) => panic!("Channel mysteriously closed on recv: {}", e),
|
||||||
|
Ok(None) => { self.done = true; None },
|
||||||
|
Ok(Some(x)) => Some(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Iterator for Receiver<T> {
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.recv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
|
||||||
|
let (undersend, underrecv) = mpsc::channel();
|
||||||
|
let sender = Sender{ underlying: undersend, done: false };
|
||||||
|
let receiver = Receiver{ underlying: underrecv, done: false };
|
||||||
|
(sender, receiver)
|
||||||
|
}
|
||||||
150
src/machine.rs
150
src/machine.rs
@@ -1,12 +1,16 @@
|
|||||||
|
use crate::endchannel::{Sender, Receiver};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::mpsc::{Sender, Receiver};
|
|
||||||
|
|
||||||
const ADD: i64 = 1;
|
const ADD: i64 = 1;
|
||||||
const MULTIPLY: i64 = 2;
|
const MULTIPLY: i64 = 2;
|
||||||
const INPUT: i64 = 3;
|
const INPUT: i64 = 3;
|
||||||
const OUTPUT: i64 = 4;
|
const OUTPUT: i64 = 4;
|
||||||
|
const JMPIF: i64 = 5;
|
||||||
|
const JMPNIF: i64 = 6;
|
||||||
|
const LESS_THAN: i64 = 7;
|
||||||
|
const EQUALS: i64 = 8;
|
||||||
const HALT: i64 = 99;
|
const HALT: i64 = 99;
|
||||||
|
|
||||||
const MODE_POSITION: i64 = 0;
|
const MODE_POSITION: i64 = 0;
|
||||||
@@ -15,7 +19,8 @@ const MODE_IMMEDIATE: i64 = 1;
|
|||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Computer {
|
pub struct Computer {
|
||||||
memory: Vec<i64>,
|
memory: Vec<i64>,
|
||||||
position: usize
|
position: usize,
|
||||||
|
done: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Computer {
|
impl Computer {
|
||||||
@@ -36,7 +41,7 @@ impl Computer {
|
|||||||
memory.push(next);
|
memory.push(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
Computer{ memory, position }
|
Computer{ memory, position, done: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(&self) {
|
pub fn show(&self) {
|
||||||
@@ -62,7 +67,7 @@ impl Computer {
|
|||||||
self.memory[idx] = val;
|
self.memory[idx] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self, input: &Receiver<i64>, output: &Sender<i64>) {
|
fn step(&mut self, input: &mut Receiver<i64>, output: &mut Sender<i64>) {
|
||||||
let next_instruction = self.read(self.position);
|
let next_instruction = self.read(self.position);
|
||||||
let opcode = next_instruction % 100;
|
let opcode = next_instruction % 100;
|
||||||
let arg1mode = (next_instruction / 100) % 10;
|
let arg1mode = (next_instruction / 100) % 10;
|
||||||
@@ -88,16 +93,53 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
INPUT => {
|
INPUT => {
|
||||||
let dest = self.read(self.position + 1) as usize;
|
let dest = self.read(self.position + 1) as usize;
|
||||||
let val = input.recv().expect("Failed to read input value from channel.");
|
let val = input.recv().expect("Failed to get input!");
|
||||||
self.write(dest, val);
|
self.write(dest, val);
|
||||||
self.position += 2;
|
self.position += 2;
|
||||||
}
|
}
|
||||||
OUTPUT => {
|
OUTPUT => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
output.send(arg1).expect("Send failed.");
|
output.send(arg1);
|
||||||
self.position += 2;
|
self.position += 2;
|
||||||
}
|
}
|
||||||
HALT => {}
|
JMPIF => {
|
||||||
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
|
if arg1 != 0 {
|
||||||
|
self.position = arg2 as usize;
|
||||||
|
} else {
|
||||||
|
self.position += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JMPNIF => {
|
||||||
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
|
if arg1 == 0 {
|
||||||
|
self.position = arg2 as usize;
|
||||||
|
} else {
|
||||||
|
self.position += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LESS_THAN => {
|
||||||
|
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, if arg1 < arg2 { 1 } else { 0 });
|
||||||
|
self.position += 4;
|
||||||
|
}
|
||||||
|
EQUALS => {
|
||||||
|
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, if arg1 == arg2 { 1 } else { 0 });
|
||||||
|
self.position += 4;
|
||||||
|
}
|
||||||
|
HALT => {
|
||||||
|
output.conclude();
|
||||||
|
self.done = true;
|
||||||
|
}
|
||||||
/* */
|
/* */
|
||||||
unknown_pos =>
|
unknown_pos =>
|
||||||
panic!("Unknown instruction {}", unknown_pos)
|
panic!("Unknown instruction {}", unknown_pos)
|
||||||
@@ -105,10 +147,10 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn halted(&self) -> bool {
|
fn halted(&self) -> bool {
|
||||||
self.read(self.position) == HALT
|
self.done
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, input: &Receiver<i64>, output: &Sender<i64>) {
|
pub fn run(&mut self, input: &mut Receiver<i64>, output: &mut Sender<i64>) {
|
||||||
while !self.halted() {
|
while !self.halted() {
|
||||||
self.step(input, output);
|
self.step(input, output);
|
||||||
}
|
}
|
||||||
@@ -116,43 +158,87 @@ impl Computer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use std::sync::mpsc::channel;
|
use crate::endchannel::channel;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn run_example(computer: Vec<i64>, inputs: Vec<i64>, targets: Vec<i64>) {
|
||||||
|
let mut day5a = Computer{ memory: computer, position: 0, done: false };
|
||||||
|
let ( mysend, mut corecv) = channel();
|
||||||
|
let (mut cosend, myrecv) = channel();
|
||||||
|
for i in inputs.iter() {
|
||||||
|
mysend.send(*i);
|
||||||
|
}
|
||||||
|
day5a.run(&mut corecv, &mut cosend);
|
||||||
|
let outputs: Vec<i64> = myrecv.collect();
|
||||||
|
assert_eq!(targets, outputs);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
let (deadsend, deadrecv) = channel();
|
let (mut deadsend, mut 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, done: false };
|
||||||
let answer1 = Computer{ memory: vec![2,0,0,0,99], position: 4 };
|
let answer1 = Computer{ memory: vec![2,0,0,0,99], position: 4, done: false };
|
||||||
example1.step(&deadrecv, &deadsend);
|
example1.step(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example1, answer1);
|
assert_eq!(example1, answer1);
|
||||||
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, done: false };
|
||||||
let answer2 = Computer{ memory: vec![2,3,0,6,99], position: 4 };
|
let answer2 = Computer{ memory: vec![2,3,0,6,99], position: 4, done: false };
|
||||||
example2.step(&deadrecv, &deadsend);
|
example2.step(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example2, answer2);
|
assert_eq!(example2, answer2);
|
||||||
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, done: false };
|
||||||
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, done: false };
|
||||||
example3.step(&deadrecv, &deadsend);
|
example3.step(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example3, answer3);
|
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 mut example4 = Computer{ memory: vec![1,1,1,4,99,5,6,0,99], position: 0, done: false };
|
||||||
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, done: true };
|
||||||
example4.run(&deadrecv, &deadsend);
|
example4.run(&mut deadrecv, &mut 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 mut example5 = Computer{ memory: vec![1002,4,3,4,33], position: 0, done: false };
|
||||||
let answer5 = Computer{ memory: vec![1002,4,3,4,99], position: 4 };
|
let answer5 = Computer{ memory: vec![1002,4,3,4,99], position: 4, done: true };
|
||||||
example5.run(&deadrecv, &deadsend);
|
example5.run(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example5, answer5);
|
assert_eq!(example5, answer5);
|
||||||
|
assert!(example5.halted());
|
||||||
|
|
||||||
let mut example6 = Computer::from_string("1101,100,-1,4,0", 0);
|
let mut example6 = Computer::from_string("1101,100,-1,4,0", 0);
|
||||||
let answer6 = Computer{ memory: vec![1101,100,-1,4,99], position: 4 };
|
let answer6 = Computer{ memory: vec![1101,100,-1,4,99], position: 4, done: true };
|
||||||
example6.run(&deadrecv, &deadsend);
|
example6.run(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example6, answer6);
|
assert_eq!(example6, answer6);
|
||||||
}
|
assert!(example6.halted());
|
||||||
|
|
||||||
|
let mut day5a = Computer::load("inputs/day5", 0);
|
||||||
|
let target = vec![0,0,0,0,0,0,0,0,0,7_259_358];
|
||||||
|
let ( mysend, mut corecv) = channel();
|
||||||
|
let (mut cosend, myrecv) = channel();
|
||||||
|
mysend.send(1);
|
||||||
|
day5a.run(&mut corecv, &mut cosend);
|
||||||
|
let outputs: Vec<i64> = myrecv.collect();
|
||||||
|
assert_eq!(target, outputs);
|
||||||
|
|
||||||
|
run_example(vec![3,9,8,9,10,9,4,9,99,-1,8], vec![8], vec![1]);
|
||||||
|
run_example(vec![3,9,8,9,10,9,4,9,99,-1,8], vec![9], vec![0]);
|
||||||
|
run_example(vec![3,9,7,9,10,9,4,9,99,-1,8], vec![4], vec![1]);
|
||||||
|
run_example(vec![3,9,7,9,10,9,4,9,99,-1,8], vec![8], vec![0]);
|
||||||
|
run_example(vec![3,9,7,9,10,9,4,9,99,-1,8], vec![9], vec![0]);
|
||||||
|
run_example(vec![3,3,1108,-1,8,3,4,3,99], vec![8], vec![1]);
|
||||||
|
run_example(vec![3,3,1108,-1,8,3,4,3,99], vec![9], vec![0]);
|
||||||
|
run_example(vec![3,3,1107,-1,8,3,4,3,99], vec![4], vec![1]);
|
||||||
|
run_example(vec![3,3,1107,-1,8,3,4,3,99], vec![8], vec![0]);
|
||||||
|
run_example(vec![3,3,1107,-1,8,3,4,3,99], vec![9], vec![0]);
|
||||||
|
run_example(vec![3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||||
|
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,
|
||||||
|
999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99],
|
||||||
|
vec![3], vec![999]);
|
||||||
|
run_example(vec![3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||||
|
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,
|
||||||
|
999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99],
|
||||||
|
vec![8], vec![1000]);
|
||||||
|
run_example(vec![3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,
|
||||||
|
1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,
|
||||||
|
999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99],
|
||||||
|
vec![192], vec![1001]);
|
||||||
|
}
|
||||||
|
|||||||
15
src/main.rs
15
src/main.rs
@@ -1,13 +1,14 @@
|
|||||||
mod args;
|
mod args;
|
||||||
|
mod endchannel;
|
||||||
mod fuel;
|
mod fuel;
|
||||||
mod machine;
|
mod machine;
|
||||||
mod wiremap;
|
mod wiremap;
|
||||||
|
|
||||||
use crate::args::Command;
|
use crate::args::Command;
|
||||||
|
use crate::endchannel::channel;
|
||||||
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() {
|
||||||
@@ -24,14 +25,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Command::RunComputer(mut initial) => {
|
Command::RunComputer(mut initial) => {
|
||||||
let (my_sender, their_receiver) = channel();
|
let (my_sender, mut their_receiver) = channel();
|
||||||
let (their_sender, my_receiver) = channel();
|
let (mut their_sender, my_receiver) = channel();
|
||||||
println!("Initial Computer:");
|
println!("Initial Computer:");
|
||||||
initial.show();
|
initial.show();
|
||||||
println!("Running, with input 1.");
|
println!("Running, with input 5.");
|
||||||
my_sender.send(1).expect("Initial send failed");
|
my_sender.send(5);
|
||||||
initial.run(&their_receiver, &their_sender);
|
initial.run(&mut their_receiver, &mut their_sender);
|
||||||
for val in my_receiver.iter() {
|
for val in my_receiver {
|
||||||
println!("Received value: {}", val);
|
println!("Received value: {}", val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user