advent-of-code/2019/intcode/src/lib.rs

58 lines
1.6 KiB
Rust
Raw Normal View History

2019-12-09 11:51:42 +01:00
use itertools::Itertools;
2019-12-09 13:25:36 +01:00
use std::convert::TryFrom;
2019-12-09 11:51:42 +01:00
use std::io::{self, BufRead};
use std::ops::Range;
2019-12-09 19:18:20 +01:00
use amplifier::*;
mod amplifier;
/**
* Construct amplifiers and run all of them for a single given input tape
* and a vector of amplifier configurations.
*
* Returns the return value of the first halted amplifier.
*/
pub fn run_for_input(input: &Vec<i64>, acc: &mut i64, amp_phases: Vec<i64>) -> i64 {
let mut amplifiers: Vec<_> = amp_phases
2019-12-09 13:25:36 +01:00
.into_iter()
2019-12-09 19:18:20 +01:00
.map(|amp| Amplifier {
2019-12-09 13:25:36 +01:00
tape: input.clone(),
pos: 0,
params: vec![amp],
})
.collect();
2019-12-09 19:18:20 +01:00
for state in (0..amplifiers.len()).cycle() {
let amplifier = amplifiers.get_mut(state).unwrap();
amplifier.params.insert(0, *acc);
match amplifier.run() {
2019-12-09 13:25:36 +01:00
Err(output) => *acc = output,
Ok(_) => break,
}
}
*acc
}
2019-12-09 19:18:20 +01:00
/**
* Convenience method for day 7.
* Will try all combinations of parameters in the given range and return the maximum result.
*/
2019-12-09 13:25:36 +01:00
pub fn find_max(range: Range<i64>, input: &Vec<i64>) -> Option<i64> {
usize::try_from(range.end - range.start)
.ok()
.and_then(|len| {
range
.permutations(len)
.scan(0, |&mut mut acc, amps| {
Some(run_for_input(input, &mut acc, amps))
2019-12-09 11:51:42 +01:00
})
2019-12-09 13:25:36 +01:00
.max()
2019-12-09 11:51:42 +01:00
})
}
#[rustfmt::skip]
pub fn read_input() -> Vec<i64> {
io::stdin().lock().lines().next().unwrap().unwrap().split(',').map(|n| n.parse().unwrap()).collect()
}
#[cfg(test)]
mod tests;