year2019/
day07.rs

1use crate::intcode::features::Day05Part2Features;
2use crate::intcode::{Event, 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
29                match amplifier.run::<Day05Part2Features>() {
30                    Event::Halt => panic!("expected amplifier to output signal"),
31                    Event::Input => panic!("expected amplifier to only consume two inputs"),
32                    Event::Output(x) => signal = x,
33                }
34            }
35            signal
36        })
37    }
38
39    #[must_use]
40    pub fn part2(&self) -> i64 {
41        let mut amplifiers: [Interpreter; 5] = std::array::from_fn(|_| self.interpreter.clone());
42        Self::best_signal(5..10, |phases| {
43            for (amplifier, &phase) in amplifiers.iter_mut().zip(&phases) {
44                amplifier.clone_from(&self.interpreter);
45                amplifier.push_input(phase);
46            }
47
48            let mut signal = 0;
49            loop {
50                for amplifier in &mut amplifiers {
51                    amplifier.push_input(signal);
52
53                    match amplifier.run::<Day05Part2Features>() {
54                        Event::Halt => return signal,
55                        Event::Input => {
56                            panic!("expected amplifier to only consume one input per cycle")
57                        }
58                        Event::Output(x) => signal = x,
59                    }
60                }
61            }
62        })
63    }
64
65    #[inline]
66    fn best_signal(phases: Range<i64>, mut f: impl FnMut([i64; 5]) -> i64) -> i64 {
67        let mut best = i64::MIN;
68        for a in phases.start..phases.end {
69            for b in phases.start..phases.end {
70                if b == a {
71                    continue;
72                }
73                for c in phases.start..phases.end {
74                    if c == a || c == b {
75                        continue;
76                    }
77                    for d in phases.start..phases.end {
78                        if d == a || d == b || d == c {
79                            continue;
80                        }
81                        for e in phases.start..phases.end {
82                            if e == a || e == b || e == c || e == d {
83                                continue;
84                            }
85                            best = best.max(f([a, b, c, d, e]));
86                        }
87                    }
88                }
89            }
90        }
91        best
92    }
93}
94
95examples!(Day07 -> (i64, i64) [
96    {
97        input: "3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0",
98        part1: 43210,
99    },
100    {
101        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",
102        part1: 54321,
103    },
104    {
105        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",
106        part1: 65210,
107    },
108    {
109        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",
110        part2: 139629729,
111    },
112    {
113        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",
114        part2: 18216,
115    },
116]);