aoc/year2019/
day07.rs

1//! # Amplification Circuit
2//!
3//! Brute force solution for both parts using the utility [`permutations`] method to test each of
4//! the possible 5! or 120 permutations of the phase settings.
5//!
6//! [`permutations`]: crate::util::slice
7use super::intcode::*;
8use crate::util::parse::*;
9use crate::util::slice::*;
10use std::array::from_fn;
11
12pub fn parse(input: &str) -> Vec<i64> {
13    input.iter_signed::<i64>().collect()
14}
15
16pub fn part1(input: &[i64]) -> i64 {
17    let mut result = 0;
18    let mut computer = Computer::new(input);
19
20    let sequence = |slice: &[i64]| {
21        let mut signal = 0;
22
23        // Send exactly 2 inputs and receive exactly 1 output per amplifier.
24        for &phase in slice {
25            computer.reset();
26            computer.input(phase);
27            computer.input(signal);
28
29            match computer.run() {
30                State::Output(next) => signal = next,
31                _ => unreachable!(),
32            }
33        }
34
35        result = result.max(signal);
36    };
37
38    [0, 1, 2, 3, 4].permutations(sequence);
39    result
40}
41
42pub fn part2(input: &[i64]) -> i64 {
43    let mut result = 0;
44    let mut computers: [Computer; 5] = from_fn(|_| Computer::new(input));
45
46    let feedback = |slice: &[i64]| {
47        // Reset state.
48        computers.iter_mut().for_each(Computer::reset);
49
50        // Send each initial phase setting exactly once.
51        for (computer, &phase) in computers.iter_mut().zip(slice.iter()) {
52            computer.input(phase);
53        }
54
55        // Chain amplifier inputs and ouputs in a loop until all threads finish.
56        let mut signal = 0;
57
58        'outer: loop {
59            for computer in &mut computers {
60                computer.input(signal);
61
62                match computer.run() {
63                    State::Output(next) => signal = next,
64                    _ => break 'outer,
65                }
66            }
67        }
68
69        result = result.max(signal);
70    };
71
72    [5, 6, 7, 8, 9].permutations(feedback);
73    result
74}