2019-12-09 23:11:59 +01:00
use amplifier ::* ;
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
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 20:28:24 +01:00
. map ( | amp | Amplifier ::new ( input . clone ( ) , 0 , vec! [ amp ] ) )
2019-12-09 13:25:36 +01:00
. 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 ;