This commit is contained in:
2019-12-16 22:06:11 -08:00
parent e8c2357556
commit f952286388
5 changed files with 143 additions and 5 deletions

1
inputs/day7 Normal file
View 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

View File

@@ -13,6 +13,7 @@ pub enum Command {
WireMap(Vec<Wire>), WireMap(Vec<Wire>),
Orbits(UniversalOrbitMap), Orbits(UniversalOrbitMap),
PasswordCrack(u32, u32), PasswordCrack(u32, u32),
Amplify(Computer),
} }
fn is_number(s: String) -> Result<(), String> { fn is_number(s: String) -> Result<(), String> {
@@ -86,6 +87,14 @@ impl Command {
.required(true) .required(true)
.validator(is_number)) .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(); .get_matches();
if let Some(problem1) = matches.subcommand_matches("fuel") { if let Some(problem1) = matches.subcommand_matches("fuel") {
@@ -138,6 +147,11 @@ impl Command {
return Command::Orbits(res); 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."); panic!("Failed to run a reasonable command.");
} }
} }

View File

@@ -13,6 +13,10 @@ impl<T> Sender<T> {
self.underlying.send(Some(t)).expect("Channel mysteriously closed on send."); 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) { pub fn conclude(&mut self) {
self.underlying.send(None).expect("Failed to close channel."); self.underlying.send(None).expect("Failed to close channel.");
self.done = true; self.done = true;

View File

@@ -1,7 +1,9 @@
use crate::endchannel::{Sender, Receiver}; use crate::endchannel::{Sender, Receiver, channel};
use std::fs; use std::fs;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::ops::Range;
use std::str; use std::str;
use std::thread;
const ADD: i64 = 1; const ADD: i64 = 1;
const MULTIPLY: i64 = 2; const MULTIPLY: i64 = 2;
@@ -155,10 +157,90 @@ impl Computer {
self.step(input, output); self.step(input, output);
} }
} }
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();
} }
#[cfg(test)] assert_eq!(previous_output.len(), 1);
use crate::endchannel::channel; 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)] #[cfg(test)]
fn run_example(computer: Vec<i64>, inputs: Vec<i64>, targets: Vec<i64>) { 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, 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], 999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99],
vec![192], vec![1001]); 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);
} }

View File

@@ -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);
}
} }
} }