95 lines
3.2 KiB
Rust
95 lines
3.2 KiB
Rust
use shared::intcode::{IntCode, SimulateStep, CELL};
|
|
|
|
pub fn run_stages(ic: &IntCode, phases: &[CELL]) -> CELL {
|
|
let mut value = 0;
|
|
for ndx in 0..5 {
|
|
let mut stage = ic.clone();
|
|
stage.next_input = Some(phases[ndx]);
|
|
stage.simulate_step().expect_wait_for_input();
|
|
stage.next_input = Some(value);
|
|
value = stage.simulate_step().expect_output();
|
|
stage.simulate_step().expect_finished();
|
|
}
|
|
value
|
|
}
|
|
|
|
pub fn run_feedback_stages(ic: &IntCode, phases: &[CELL]) -> CELL {
|
|
let mut stages = [ ic.clone(), ic.clone(), ic.clone(), ic.clone(), ic.clone() ];
|
|
// init all with phase
|
|
for ndx in 0..5 {
|
|
stages[ndx].next_input = Some(phases[ndx]);
|
|
stages[ndx].simulate_step().expect_wait_for_input();
|
|
}
|
|
|
|
let mut output = 0;
|
|
stages[0].next_input = Some(output);
|
|
let mut current_ndx = 0;
|
|
loop {
|
|
match stages[current_ndx].simulate_step() {
|
|
SimulateStep::Output(v) => {
|
|
current_ndx = (current_ndx + 1) % 5;
|
|
stages[current_ndx].next_input = Some(v);
|
|
if current_ndx == 0 {
|
|
// remember last final output
|
|
output = v;
|
|
}
|
|
},
|
|
SimulateStep::WaitForInput => {
|
|
panic!("Can't wait for new input before generating one");
|
|
},
|
|
SimulateStep::Finished => break,
|
|
}
|
|
}
|
|
|
|
assert_eq!(current_ndx, 0, "first amplifiert should be first to stop");
|
|
for ndx in current_ndx+1..5 {
|
|
stages[ndx].simulate_step().expect_finished();
|
|
}
|
|
|
|
output
|
|
}
|
|
|
|
pub fn best_amplifier(ic: &IntCode) -> (Vec<CELL>, CELL) {
|
|
use itertools::Itertools;
|
|
(0..5).permutations(5).map(|phases| {
|
|
let value = run_stages(ic, &phases);
|
|
(phases, value)
|
|
}).max_by_key(|(_, value)| *value).unwrap()
|
|
}
|
|
|
|
pub fn best_feedback_amplifier(ic: &IntCode) -> (Vec<CELL>, CELL) {
|
|
use itertools::Itertools;
|
|
(5..10).permutations(5).map(|phases| {
|
|
let value = run_feedback_stages(ic, &phases);
|
|
(phases, value)
|
|
}).max_by_key(|(_, value)| *value).unwrap()
|
|
}
|
|
|
|
fn main() {
|
|
let ic = include_str!("input.txt").parse::<IntCode>().unwrap();
|
|
|
|
let (phases, max_value) = best_amplifier(&ic);
|
|
println!("Max Value: {} (from phases: {:?}", max_value, phases);
|
|
|
|
let (phases, max_value) = best_feedback_amplifier(&ic);
|
|
println!("Max Feedback Value: {} (from phases: {:?}", max_value, phases);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod day7test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn examples1() {
|
|
assert_eq!(best_amplifier(&"3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0".parse::<IntCode>().unwrap()), (vec![4,3,2,1,0], 43210));
|
|
assert_eq!(best_amplifier(&"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".parse::<IntCode>().unwrap()), (vec![0,1,2,3,4], 54321));
|
|
assert_eq!(best_amplifier(&"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".parse::<IntCode>().unwrap()), (vec![1,0,4,3,2], 65210));
|
|
}
|
|
|
|
#[test]
|
|
fn examples2() {
|
|
assert_eq!(best_feedback_amplifier(&"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".parse::<IntCode>().unwrap()), (vec![9,8,7,6,5], 139629729));
|
|
assert_eq!(best_feedback_amplifier(&"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".parse::<IntCode>().unwrap()), (vec![9,7,8,5,6], 18216));
|
|
}
|
|
}
|