Skip to main content

year2019/
day07.rs

1use crate::intcode::features::Day05Part2Features;
2use crate::intcode::Interpreter;
3use std::ops::Range;
4use utils::prelude::*;
5
6/// Finding the maximum output of an interpreter pipeline.
7#[derive(Clone, Debug)]
8pub struct Day07 {
9    interpreter: Interpreter,
10}
11
12impl Day07 {
13    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
14        Ok(Self {
15            interpreter: Interpreter::parse(input, 1)?,
16        })
17    }
18
19    #[must_use]
20    pub fn part1(&self) -> i64 {
21        let mut amplifier = self.interpreter.clone();
22        Self::best_signal(0..5, |phases| {
23            let mut signal = 0;
24            for phase in phases {
25                amplifier.clone_from(&self.interpreter);
26                amplifier.push_input(phase);
27                amplifier.push_input(signal);
28                signal = amplifier.expect_output::<Day05Part2Features>();
29            }
30            signal
31        })
32    }
33
34    #[must_use]
35    pub fn part2(&self) -> i64 {
36        let mut amplifiers: [Interpreter; 5] = std::array::from_fn(|_| self.interpreter.clone());
37        Self::best_signal(5..10, |phases| {
38            for (amplifier, &phase) in amplifiers.iter_mut().zip(&phases) {
39                amplifier.clone_from(&self.interpreter);
40                amplifier.push_input(phase);
41            }
42
43            let mut signal = 0;
44            loop {
45                for amplifier in &mut amplifiers {
46                    amplifier.push_input(signal);
47                    let Some(output) = amplifier.next_output::<Day05Part2Features>() else {
48                        return signal;
49                    };
50                    signal = output;
51                }
52            }
53        })
54    }
55
56    #[inline]
57    fn best_signal(phases: Range<i64>, mut f: impl FnMut([i64; 5]) -> i64) -> i64 {
58        let mut best = i64::MIN;
59        for a in phases.start..phases.end {
60            for b in phases.start..phases.end {
61                if b == a {
62                    continue;
63                }
64                for c in phases.start..phases.end {
65                    if c == a || c == b {
66                        continue;
67                    }
68                    for d in phases.start..phases.end {
69                        if d == a || d == b || d == c {
70                            continue;
71                        }
72                        for e in phases.start..phases.end {
73                            if e == a || e == b || e == c || e == d {
74                                continue;
75                            }
76                            best = best.max(f([a, b, c, d, e]));
77                        }
78                    }
79                }
80            }
81        }
82        best
83    }
84}
85
86examples!(Day07 -> (i64, i64) [
87    {
88        input: "3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0",
89        part1: 43210,
90    },
91    {
92        input: "3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0",
93        part1: 54321,
94    },
95    {
96        input: "3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0",
97        part1: 65210,
98    },
99    {
100        input: "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",
101        part2: 139629729,
102    },
103    {
104        input: "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",
105        part2: 18216,
106    },
107]);