From 7beabbf7c9ec91f2212d2ed29543056a788ab15d Mon Sep 17 00:00:00 2001 From: Tyler Hallada Date: Wed, 11 Dec 2019 00:03:10 -0500 Subject: [PATCH] Completed day 7 part 2 so behind! :o --- day7/input/test4.txt | 1 + day7/input/test5.txt | 1 + day7/src/intcode.rs | 90 +++++++++++++++++----------------------- day7/src/main.rs | 98 ++++++++++++++++++++++++++++++++------------ 4 files changed, 111 insertions(+), 79 deletions(-) create mode 100644 day7/input/test4.txt create mode 100644 day7/input/test5.txt diff --git a/day7/input/test4.txt b/day7/input/test4.txt new file mode 100644 index 0000000..ad78133 --- /dev/null +++ b/day7/input/test4.txt @@ -0,0 +1 @@ +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 diff --git a/day7/input/test5.txt b/day7/input/test5.txt new file mode 100644 index 0000000..cd43fb9 --- /dev/null +++ b/day7/input/test5.txt @@ -0,0 +1 @@ +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 diff --git a/day7/src/intcode.rs b/day7/src/intcode.rs index 1c3c9b6..9dfa99e 100644 --- a/day7/src/intcode.rs +++ b/day7/src/intcode.rs @@ -12,7 +12,9 @@ type Result = result::Result>; #[derive(Debug, Clone, PartialEq)] pub struct Intcode { - integers: Vec, + pub integers: Vec, + pub pointer: usize, + pub halted: bool, } #[derive(Debug, PartialEq)] @@ -105,16 +107,23 @@ impl FromStr for Intcode { fn from_str(s: &str) -> Result { let intcode_string = s.trim().to_string(); - Ok(Intcode { - integers: intcode_string + Ok(Intcode::new( + intcode_string .split(',') .map(|code| code.parse().unwrap()) .collect(), - }) + )) } } impl Intcode { + fn new(integers: Vec) -> Intcode { + Intcode { + integers, + pointer: 0, + halted: false, + } + } fn load_parameters(&self, pointer: usize, instruction: &Instruction) -> Vec { (0..instruction.opcode.parameter_count() as usize) .map(|parameter_index| { @@ -134,13 +143,12 @@ impl Intcode { } pub fn execute(&mut self, inputs: &[i32]) -> Result> { - let mut pointer = 0; let mut input_index = 0; let mut output = vec![]; loop { - let instruction = Instruction::try_from(self.integers[pointer])?; - let parameters = self.load_parameters(pointer, &instruction); + let instruction = Instruction::try_from(self.integers[self.pointer])?; + let parameters = self.load_parameters(self.pointer, &instruction); let mut jump_pointer: Option = None; match instruction.opcode { @@ -151,6 +159,9 @@ impl Intcode { self.integers[parameters[2] as usize] = parameters[0] * parameters[1]; } Opcode::Input => { + if input_index >= inputs.len() { + break; // pause execution to wait for more input + } self.integers[parameters[0] as usize] = inputs[input_index]; input_index += 1; } @@ -182,13 +193,14 @@ impl Intcode { } } Opcode::Halt => { + self.halted = true; break; } } match jump_pointer { - Some(jump_pointer) => pointer = jump_pointer, - None => pointer += 1 + instruction.opcode.parameter_count() as usize, + Some(jump_pointer) => self.pointer = jump_pointer, + None => self.pointer += 1 + instruction.opcode.parameter_count() as usize, } } @@ -214,9 +226,7 @@ mod tests { fn reads_intcode() { assert_eq!( read_intcode(TEST_INPUT).unwrap(), - Intcode { - integers: vec![3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0] - }, + Intcode::new(vec![3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0]), ); } @@ -249,33 +259,23 @@ mod tests { #[test] fn executes_intcodes() { - let mut intcode = Intcode { - integers: vec![1, 0, 0, 0, 99], - }; + let mut intcode = Intcode::new(vec![1, 0, 0, 0, 99]); intcode.execute(&[0]).unwrap(); assert_eq!(intcode.integers, vec![2, 0, 0, 0, 99]); - let mut intcode = Intcode { - integers: vec![2, 3, 0, 3, 99], - }; + let mut intcode = Intcode::new(vec![2, 3, 0, 3, 99]); intcode.execute(&[0]).unwrap(); assert_eq!(intcode.integers, vec![2, 3, 0, 6, 99]); - let mut intcode = Intcode { - integers: vec![2, 4, 4, 5, 99, 0], - }; + let mut intcode = Intcode::new(vec![2, 4, 4, 5, 99, 0]); intcode.execute(&[0]).unwrap(); assert_eq!(intcode.integers, vec![2, 4, 4, 5, 99, 9801]); - let mut intcode = Intcode { - integers: vec![1, 1, 1, 4, 99, 5, 6, 0, 99], - }; + let mut intcode = Intcode::new(vec![1, 1, 1, 4, 99, 5, 6, 0, 99]); intcode.execute(&[0]).unwrap(); assert_eq!(intcode.integers, vec![30, 1, 1, 4, 2, 5, 6, 0, 99]); - let mut intcode = Intcode { - integers: vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50], - }; + let mut intcode = Intcode::new(vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50]); intcode.execute(&[0]).unwrap(); assert_eq!( intcode.integers, @@ -285,55 +285,41 @@ mod tests { #[test] fn less_and_equal_outputs() { - let intcode = Intcode { - integers: vec![3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8], - }; + let intcode = Intcode::new(vec![3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8]); assert_eq!(intcode.clone().execute(&[8]).unwrap(), vec![1]); assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]); - let intcode = Intcode { - integers: vec![3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8], - }; + let intcode = Intcode::new(vec![3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8]); assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![1]); assert_eq!(intcode.clone().execute(&[9]).unwrap(), vec![0]); - let intcode = Intcode { - integers: vec![3, 3, 1108, -1, 8, 3, 4, 3, 99], - }; + let intcode = Intcode::new(vec![3, 3, 1108, -1, 8, 3, 4, 3, 99]); assert_eq!(intcode.clone().execute(&[8]).unwrap(), vec![1]); assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]); - let intcode = Intcode { - integers: vec![3, 3, 1107, -1, 8, 3, 4, 3, 99], - }; + let intcode = Intcode::new(vec![3, 3, 1107, -1, 8, 3, 4, 3, 99]); assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![1]); assert_eq!(intcode.clone().execute(&[9]).unwrap(), vec![0]); } #[test] fn jump_outputs() { - let intcode = Intcode { - integers: vec![3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9], - }; + let intcode = Intcode::new(vec![3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9]); assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]); assert_eq!(intcode.clone().execute(&[1]).unwrap(), vec![1]); - let intcode = Intcode { - integers: vec![3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1], - }; + let intcode = Intcode::new(vec![3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1]); assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]); assert_eq!(intcode.clone().execute(&[1]).unwrap(), vec![1]); } #[test] fn larger_part2_intcode() { - let intcode = Intcode { - integers: vec![ + let intcode = Intcode::new(vec![ 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 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, - ], - }; + ]); assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![999]); assert_eq!(intcode.clone().execute(&[8]).unwrap(), vec![1000]); assert_eq!(intcode.clone().execute(&[9]).unwrap(), vec![1001]); @@ -341,11 +327,9 @@ mod tests { #[test] fn multiple_input_intcode() { - let intcode = Intcode { - integers: vec![ + let intcode = Intcode::new(vec![ 3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0, - ], - }; + ]); assert_eq!(intcode.clone().execute(&[1, 1]).unwrap(), vec![11]); } } diff --git a/day7/src/main.rs b/day7/src/main.rs index 499a60d..1e3a02b 100644 --- a/day7/src/main.rs +++ b/day7/src/main.rs @@ -14,69 +14,84 @@ type Result = result::Result>; #[derive(Debug, Clone, PartialEq)] struct Amplifier { intcode: Intcode, - phase_setting: i32, } impl Amplifier { - fn new(intcode: Intcode, phase_setting: i32) -> Amplifier { + fn new(intcode: Intcode) -> Amplifier { Amplifier { intcode: intcode, - phase_setting: phase_setting, } } - fn execute(&self, input: i32) -> Result { - let mut intcode = self.intcode.clone(); - let output = intcode.execute(&[self.phase_setting, input])?; - dbg!(&output); - Ok(output[0]) + fn reset_intcode(&mut self, intcode: Intcode) { + self.intcode = intcode; + } + + fn execute(&mut self, input: i32) -> Result> { + let output = self.intcode.execute(&[input])?; + Ok(output) } } #[derive(Debug, Clone, PartialEq)] struct AmplificationCircuit { amplifiers: Vec, + intcode: Intcode, } impl AmplificationCircuit { fn new( intcode: Intcode, amplifier_count: usize, - initial_phase_settings: &[i32], ) -> AmplificationCircuit { AmplificationCircuit { amplifiers: (0..amplifier_count) - .map(|index| Amplifier::new(intcode.clone(), initial_phase_settings[index])) + .map(|_| Amplifier::new(intcode.clone())) .collect(), + intcode, } } - fn set_phase_settings(&mut self, phase_settings: &[i32; 5]) { + fn set_phase_settings(&mut self, phase_settings: &[i32; 5]) -> Result<()> { for (index, phase_setting) in phase_settings.iter().enumerate() { - self.amplifiers[index].phase_setting = *phase_setting; + self.amplifiers[index].execute(*phase_setting)?; + } + Ok(()) + } + + fn reset_circuit(&mut self) { + for amplifier in self.amplifiers.iter_mut() { + amplifier.reset_intcode(self.intcode.clone()); } } - fn execute_circuit(&self, input_signal: i32) -> Result { + fn execute_circuit(&mut self, input_signal: i32) -> Result { let mut input = input_signal; - for amplifier in self.amplifiers.iter() { - input = amplifier.execute(input)?; + while !self.amplifiers[4].intcode.halted { + for amplifier in self.amplifiers.iter_mut() { + input = amplifier.execute(input)?[0]; + } } Ok(input) } - fn find_max_output(&mut self, input_signal: i32) -> Result { - let mut phase_setting: [i32; 5] = [0, 1, 2, 3, 4]; + fn find_max_output( + &mut self, + input_signal: i32, + phase_setting_options: [i32; 5], + ) -> Result { + let mut phase_setting: [i32; 5] = phase_setting_options; let mut max_output = 0; let heap = Heap::new(&mut phase_setting); for permutation in heap { - self.set_phase_settings(&permutation); + self.set_phase_settings(&permutation)?; let output = self.execute_circuit(input_signal)?; if output > max_output { max_output = output; } + self.reset_circuit(); } Ok(max_output) @@ -85,12 +100,14 @@ impl AmplificationCircuit { fn solve_part1() -> Result { let intcode = read_intcode(INPUT)?; - let mut circuit = AmplificationCircuit::new(intcode, 5, &[0, 0, 0, 0, 0]); - Ok(circuit.find_max_output(0)?) + let mut circuit = AmplificationCircuit::new(intcode, 5); + Ok(circuit.find_max_output(0, [0, 1, 2, 3, 4])?) } fn solve_part2() -> Result { - Ok(0) + let intcode = read_intcode(INPUT)?; + let mut circuit = AmplificationCircuit::new(intcode, 5); + Ok(circuit.find_max_output(0, [5, 6, 7, 8, 9])?) } fn main() -> Result<()> { @@ -107,19 +124,24 @@ mod tests { const TEST_INPUT1: &str = "input/test1.txt"; const TEST_INPUT2: &str = "input/test2.txt"; const TEST_INPUT3: &str = "input/test3.txt"; + const TEST_INPUT4: &str = "input/test4.txt"; + const TEST_INPUT5: &str = "input/test5.txt"; #[test] fn executes_amplifier_circuits() { let intcode = read_intcode(TEST_INPUT1).unwrap(); - let circuit = AmplificationCircuit::new(intcode, 5, &[4, 3, 2, 1, 0]); + let mut circuit = AmplificationCircuit::new(intcode, 5); + circuit.set_phase_settings(&[4, 3, 2, 1, 0]).unwrap(); assert_eq!(circuit.execute_circuit(0).unwrap(), 43210); let intcode = read_intcode(TEST_INPUT2).unwrap(); - let circuit = AmplificationCircuit::new(intcode, 5, &[0, 1, 2, 3, 4]); + let mut circuit = AmplificationCircuit::new(intcode, 5); + circuit.set_phase_settings(&[0, 1, 2, 3, 4]).unwrap(); assert_eq!(circuit.execute_circuit(0).unwrap(), 54321); let intcode = read_intcode(TEST_INPUT3).unwrap(); - let circuit = AmplificationCircuit::new(intcode, 5, &[1, 0, 4, 3, 2]); + let mut circuit = AmplificationCircuit::new(intcode, 5); + circuit.set_phase_settings(&[1, 0, 4, 3, 2]).unwrap(); assert_eq!(circuit.execute_circuit(0).unwrap(), 65210); } @@ -129,8 +151,32 @@ mod tests { let outputs = [43210, 54321, 65210]; for (input, output) in inputs.iter().zip(outputs.iter()) { let intcode = read_intcode(input).unwrap(); - let mut circuit = AmplificationCircuit::new(intcode, 5, &[0, 0, 0, 0, 0]); - assert_eq!(circuit.find_max_output(0).unwrap(), *output); + let mut circuit = AmplificationCircuit::new(intcode, 5); + assert_eq!(circuit.find_max_output(0, [0, 1, 2, 3, 4]).unwrap(), *output); + } + } + + #[test] + fn executes_feedback_loop_amplifier_circuits() { + let intcode = read_intcode(TEST_INPUT4).unwrap(); + let mut circuit = AmplificationCircuit::new(intcode, 5); + circuit.set_phase_settings(&[9, 8, 7, 6, 5]).unwrap(); + assert_eq!(circuit.execute_circuit(0).unwrap(), 139629729); + + let intcode = read_intcode(TEST_INPUT5).unwrap(); + let mut circuit = AmplificationCircuit::new(intcode, 5); + circuit.set_phase_settings(&[9, 7, 8, 5, 6]).unwrap(); + assert_eq!(circuit.execute_circuit(0).unwrap(), 18216); + } + + #[test] + fn finds_max_outputs_of_feedback_loop_circuits() { + let inputs = [TEST_INPUT4, TEST_INPUT5]; + let outputs = [139629729, 18216]; + for (input, output) in inputs.iter().zip(outputs.iter()) { + let intcode = read_intcode(input).unwrap(); + let mut circuit = AmplificationCircuit::new(intcode, 5); + assert_eq!(circuit.find_max_output(0, [5, 6, 7, 8, 9]).unwrap(), *output); } } }