1use crate::intcode::features::Day05Part2Features;
2use crate::intcode::{Event, Interpreter};
3use std::ops::Range;
4use utils::prelude::*;
5
6#[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]);