Completed day 7 part 2

so behind! :o
This commit is contained in:
Tyler Hallada 2019-12-11 00:03:10 -05:00
parent 74d77382dd
commit 7beabbf7c9
4 changed files with 111 additions and 79 deletions

1
day7/input/test4.txt Normal file
View File

@ -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

1
day7/input/test5.txt Normal file
View File

@ -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

View File

@ -12,7 +12,9 @@ type Result<T> = result::Result<T, Box<dyn Error>>;
#[derive(Debug, Clone, PartialEq)]
pub struct Intcode {
integers: Vec<i32>,
pub integers: Vec<i32>,
pub pointer: usize,
pub halted: bool,
}
#[derive(Debug, PartialEq)]
@ -105,16 +107,23 @@ impl FromStr for Intcode {
fn from_str(s: &str) -> Result<Intcode> {
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<i32>) -> Intcode {
Intcode {
integers,
pointer: 0,
halted: false,
}
}
fn load_parameters(&self, pointer: usize, instruction: &Instruction) -> Vec<i32> {
(0..instruction.opcode.parameter_count() as usize)
.map(|parameter_index| {
@ -134,13 +143,12 @@ impl Intcode {
}
pub fn execute(&mut self, inputs: &[i32]) -> Result<Vec<i32>> {
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<usize> = 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]);
}
}

View File

@ -14,69 +14,84 @@ type Result<T> = result::Result<T, Box<dyn Error>>;
#[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<i32> {
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<Vec<i32>> {
let output = self.intcode.execute(&[input])?;
Ok(output)
}
}
#[derive(Debug, Clone, PartialEq)]
struct AmplificationCircuit {
amplifiers: Vec<Amplifier>,
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<i32> {
fn execute_circuit(&mut self, input_signal: i32) -> Result<i32> {
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<i32> {
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<i32> {
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<i32> {
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<i32> {
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);
}
}
}