Day 7!
This commit is contained in:
1
inputs/day7
Normal file
1
inputs/day7
Normal file
@@ -0,0 +1 @@
|
||||
3,8,1001,8,10,8,105,1,0,0,21,38,63,72,81,106,187,268,349,430,99999,3,9,101,5,9,9,1002,9,3,9,101,3,9,9,4,9,99,3,9,102,3,9,9,101,4,9,9,1002,9,2,9,1001,9,2,9,1002,9,4,9,4,9,99,3,9,1001,9,3,9,4,9,99,3,9,102,5,9,9,4,9,99,3,9,102,4,9,9,1001,9,2,9,1002,9,5,9,1001,9,2,9,102,3,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,99
|
||||
14
src/args.rs
14
src/args.rs
@@ -13,6 +13,7 @@ pub enum Command {
|
||||
WireMap(Vec<Wire>),
|
||||
Orbits(UniversalOrbitMap),
|
||||
PasswordCrack(u32, u32),
|
||||
Amplify(Computer),
|
||||
}
|
||||
|
||||
fn is_number(s: String) -> Result<(), String> {
|
||||
@@ -86,6 +87,14 @@ impl Command {
|
||||
.required(true)
|
||||
.validator(is_number))
|
||||
)
|
||||
.subcommand(SubCommand::with_name("amplify")
|
||||
.about("run the given amplifer computer")
|
||||
.arg(Arg::with_name("COMPUTER")
|
||||
.index(1)
|
||||
.help("The computer to run.")
|
||||
.required(true)
|
||||
.validator(is_file))
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
if let Some(problem1) = matches.subcommand_matches("fuel") {
|
||||
@@ -138,6 +147,11 @@ impl Command {
|
||||
return Command::Orbits(res);
|
||||
}
|
||||
|
||||
if let Some(problem6) = matches.subcommand_matches("amplify") {
|
||||
let computer = Computer::load(problem6.value_of("COMPUTER").unwrap(), 0);
|
||||
return Command::Amplify(computer);
|
||||
}
|
||||
|
||||
panic!("Failed to run a reasonable command.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ impl<T> Sender<T> {
|
||||
self.underlying.send(Some(t)).expect("Channel mysteriously closed on send.");
|
||||
}
|
||||
|
||||
pub fn send_ignore_error(&self, t: T) {
|
||||
let _ = self.underlying.send(Some(t));
|
||||
}
|
||||
|
||||
pub fn conclude(&mut self) {
|
||||
self.underlying.send(None).expect("Failed to close channel.");
|
||||
self.done = true;
|
||||
|
||||
120
src/machine.rs
120
src/machine.rs
@@ -1,7 +1,9 @@
|
||||
use crate::endchannel::{Sender, Receiver};
|
||||
use crate::endchannel::{Sender, Receiver, channel};
|
||||
use std::fs;
|
||||
use std::iter::FromIterator;
|
||||
use std::ops::Range;
|
||||
use std::str;
|
||||
use std::thread;
|
||||
|
||||
const ADD: i64 = 1;
|
||||
const MULTIPLY: i64 = 2;
|
||||
@@ -155,10 +157,90 @@ impl Computer {
|
||||
self.step(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::endchannel::channel;
|
||||
pub fn serialize(&self, inputs: Vec<i64>) -> i64 {
|
||||
let mut previous_output = vec![0];
|
||||
|
||||
for input in inputs.iter() {
|
||||
let mut my_machine = self.clone();
|
||||
let ( mysend, mut corecv) = channel();
|
||||
let (mut cosend, myrecv) = channel();
|
||||
mysend.send(*input);
|
||||
for i in previous_output.iter() {
|
||||
mysend.send(*i);
|
||||
}
|
||||
my_machine.run(&mut corecv, &mut cosend);
|
||||
previous_output = myrecv.collect();
|
||||
}
|
||||
|
||||
assert_eq!(previous_output.len(), 1);
|
||||
previous_output[0]
|
||||
}
|
||||
|
||||
pub fn find_best_signal<F>(&self, range: Range<i64>, f: F) -> (i64, Vec<i64>)
|
||||
where F: Fn(Vec<i64>) -> i64
|
||||
{
|
||||
let mut best_score = 0;
|
||||
let mut best_result = vec![];
|
||||
|
||||
for a in range.clone() {
|
||||
for b in range.clone() {
|
||||
if b == a { continue; }
|
||||
for c in range.clone() {
|
||||
if c == a || c == b { continue; }
|
||||
for d in range.clone() {
|
||||
if d == c || d == b || d == a { continue; }
|
||||
for e in range.clone() {
|
||||
if e == d || e == c || e == b || e == a { continue; }
|
||||
let inputs = vec![a,b,c,d,e];
|
||||
let result = f(inputs);
|
||||
if result > best_score {
|
||||
best_score = result;
|
||||
best_result = vec![a,b,c,d,e];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(best_score, best_result)
|
||||
}
|
||||
|
||||
pub fn amplifier(&self, settings: Vec<i64>) -> i64 {
|
||||
assert_eq!(settings.len(), 5);
|
||||
|
||||
let mut machine_a = self.clone();
|
||||
let mut machine_b = self.clone();
|
||||
let mut machine_c = self.clone();
|
||||
let mut machine_d = self.clone();
|
||||
let mut machine_e = self.clone();
|
||||
|
||||
let ( send_ha, mut recv_ha) = channel(); send_ha.send(settings[0]);
|
||||
let (mut send_ab, mut recv_ab) = channel(); send_ab.send(settings[1]);
|
||||
let (mut send_bc, mut recv_bc) = channel(); send_bc.send(settings[2]);
|
||||
let (mut send_cd, mut recv_cd) = channel(); send_cd.send(settings[3]);
|
||||
let (mut send_de, mut recv_de) = channel(); send_de.send(settings[4]);
|
||||
let (mut send_eh, recv_eh) = channel();
|
||||
|
||||
thread::spawn(move || { machine_a.run(&mut recv_ha, &mut send_ab) });
|
||||
thread::spawn(move || { machine_b.run(&mut recv_ab, &mut send_bc) });
|
||||
thread::spawn(move || { machine_c.run(&mut recv_bc, &mut send_cd) });
|
||||
thread::spawn(move || { machine_d.run(&mut recv_cd, &mut send_de) });
|
||||
thread::spawn(move || { machine_e.run(&mut recv_de, &mut send_eh) });
|
||||
|
||||
send_ha.send(0); // kick it off
|
||||
|
||||
let mut last_output = 0;
|
||||
|
||||
for output in recv_eh {
|
||||
last_output = output;
|
||||
send_ha.send_ignore_error(output);
|
||||
}
|
||||
|
||||
last_output
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn run_example(computer: Vec<i64>, inputs: Vec<i64>, targets: Vec<i64>) {
|
||||
@@ -241,4 +323,34 @@ fn test_examples() {
|
||||
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]);
|
||||
|
||||
let example7a = Computer::from_string("3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0", 0);
|
||||
let result7a = example7a.serialize(vec![4,3,2,1,0]);
|
||||
assert_eq!(43210, result7a);
|
||||
let example7b = Computer::from_string("3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0", 0);
|
||||
let result7b = example7b.serialize(vec![0,1,2,3,4]);
|
||||
assert_eq!(54321, result7b);
|
||||
let example7c = Computer::from_string("3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0", 0);
|
||||
let target7c = 65210;
|
||||
let result7c = example7c.serialize(vec![1,0,4,3,2]);
|
||||
assert_eq!(target7c, result7c);
|
||||
let result7c2 = example7c.serialize(vec![1,0,4,3,2]);
|
||||
assert_eq!(target7c, result7c2);
|
||||
assert_eq!(result7c2, 65210);
|
||||
assert_eq!(example7c.find_best_signal(0..5, |x| example7c.serialize(x)).1, vec![1,0,4,3,2]);
|
||||
let day7a = Computer::load("inputs/day7", 0);
|
||||
let (day7score, day7settings) = day7a.find_best_signal(0..5, |x| day7a.serialize(x));
|
||||
assert_eq!(day7score, 206580);
|
||||
assert_eq!(day7settings, vec![2,0,1,4,3]);
|
||||
|
||||
let example7e = Computer::from_string("3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5", 0);
|
||||
assert_eq!(139629729, example7e.amplifier(vec![9,8,7,6,5]));
|
||||
let (example7es, example7et) = example7e.find_best_signal(5..10, |x| example7e.amplifier(x));
|
||||
assert_eq!(139629729, example7es);
|
||||
assert_eq!(vec![9,8,7,6,5], example7et);
|
||||
let example7f = Computer::from_string("3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10", 0);
|
||||
assert_eq!(18216, example7f.amplifier(vec![9,7,8,5,6]));
|
||||
let (example7fs, example7ft) = example7f.find_best_signal(5..10, |x| example7f.amplifier(x));
|
||||
assert_eq!(18216, example7fs);
|
||||
assert_eq!(vec![9,7,8,5,6], example7ft);
|
||||
}
|
||||
|
||||
@@ -127,5 +127,12 @@ fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Command::Amplify(computer) => {
|
||||
let (amount_a, settings_a) = computer.find_best_signal(0..5, |x| computer.serialize(x));
|
||||
println!("Best signal without loopback is {} @ {:?}", amount_a, settings_a);
|
||||
let (amount_b, settings_b) = computer.find_best_signal(5..10, |x| computer.amplifier(x));
|
||||
println!("Best signal with loopback is {} @ {:?}", amount_b, settings_b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user