Day 23, part 1.
This commit is contained in:
@@ -10,5 +10,6 @@ edition = "2018"
|
|||||||
bytecount = "^0.6.0"
|
bytecount = "^0.6.0"
|
||||||
clap = "^2.33.0"
|
clap = "^2.33.0"
|
||||||
image = "^0.22.0"
|
image = "^0.22.0"
|
||||||
|
itertools = "^0.8.0"
|
||||||
rand = "^0.7"
|
rand = "^0.7"
|
||||||
terminal_graphics = "^0.1.5"
|
terminal_graphics = "^0.1.5"
|
||||||
|
|||||||
1
inputs/day23
Normal file
1
inputs/day23
Normal file
File diff suppressed because one or more lines are too long
@@ -9,6 +9,8 @@ mod repair;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod robot;
|
mod robot;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
mod router;
|
||||||
|
#[cfg(test)]
|
||||||
mod scaffold;
|
mod scaffold;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tractor;
|
mod tractor;
|
||||||
|
|||||||
121
src/router.rs
Normal file
121
src/router.rs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
use crate::machine::{Computer, RunResult};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
struct ComputerState {
|
||||||
|
next: Box<dyn FnOnce(i64) -> Computer>,
|
||||||
|
input_queue: VecDeque<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComputerState {
|
||||||
|
fn new(mut c: Computer, address: i64) -> ComputerState {
|
||||||
|
let mut sent_address = false;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match c.run() {
|
||||||
|
RunResult::Continue(next) =>
|
||||||
|
c = next,
|
||||||
|
RunResult::Halted(_) =>
|
||||||
|
panic!("Computer halted right away!"),
|
||||||
|
RunResult::Output(_, _) =>
|
||||||
|
panic!("Computer sent output right away!"),
|
||||||
|
RunResult::Input(f) if sent_address =>
|
||||||
|
return ComputerState {
|
||||||
|
next: f,
|
||||||
|
input_queue: VecDeque::new(),
|
||||||
|
},
|
||||||
|
RunResult::Input(f) => {
|
||||||
|
c = f(address);
|
||||||
|
sent_address = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(mut self, output: &mut VecDeque<i64>) -> Option<Self> {
|
||||||
|
let mut c = match self.input_queue.pop_front() {
|
||||||
|
None => (self.next)(-1),
|
||||||
|
Some(x) => (self.next)(x),
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match c.run() {
|
||||||
|
RunResult::Continue(next) =>
|
||||||
|
c = next,
|
||||||
|
RunResult::Halted(_) =>
|
||||||
|
return None,
|
||||||
|
RunResult::Output(o, next) => {
|
||||||
|
output.push_back(o);
|
||||||
|
c = next;
|
||||||
|
}
|
||||||
|
RunResult::Input(f) =>
|
||||||
|
match self.input_queue.pop_front() {
|
||||||
|
None => {
|
||||||
|
self.next = f;
|
||||||
|
return Some(self);
|
||||||
|
}
|
||||||
|
Some(x) =>
|
||||||
|
c = f(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Router {
|
||||||
|
map: HashMap<usize, ComputerState>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Router {
|
||||||
|
fn new(file: &str, nodes: Range<usize>) -> Router {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
let c = Computer::load(file);
|
||||||
|
|
||||||
|
for i in nodes {
|
||||||
|
map.insert(i, ComputerState::new(c.clone(), i as i64));
|
||||||
|
}
|
||||||
|
|
||||||
|
Router{ map }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn step(mut self) -> Self {
|
||||||
|
let mut outputs = VecDeque::new();
|
||||||
|
let mut res = HashMap::new();
|
||||||
|
|
||||||
|
for (key, val) in self.map.drain() {
|
||||||
|
match val.run(&mut outputs) {
|
||||||
|
None => {},
|
||||||
|
Some(new_state) => {
|
||||||
|
let _ = res.insert(key, new_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (dest, x, y) in outputs.drain(0..).tuples() {
|
||||||
|
match res.get_mut(&(dest as usize)) {
|
||||||
|
None =>
|
||||||
|
panic!("Unknown destination {} (x {}, y {})", dest, x, y),
|
||||||
|
Some(state) => {
|
||||||
|
state.input_queue.push_back(x);
|
||||||
|
state.input_queue.push_back(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Router{ map: res }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(mut self) -> Self {
|
||||||
|
while self.map.len() > 0 {
|
||||||
|
self = self.step();
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day23a() {
|
||||||
|
let router = Router::new("inputs/day23", 0..50);
|
||||||
|
router.run();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user