aoc/year2019/
day23.rs

1//! # Category Six
2//!
3//! Solves both part one and two simultaneously. A nice benefit of our intcode computer is that it
4//! returns [`State::Input`] when the input queue is empty, making it easy to detect an
5//! idle network.
6use super::intcode::*;
7use crate::util::parse::*;
8
9type Input = (i64, i64);
10
11pub fn parse(input: &str) -> Input {
12    let code: Vec<_> = input.iter_signed().collect();
13    let mut network: Vec<_> = (0..50)
14        .map(|address| {
15            let mut computer = Computer::new(&code);
16            computer.input(address);
17            computer
18        })
19        .collect();
20
21    let mut sent = Vec::new();
22    let mut nat_x = 0;
23    let mut nat_y = 0;
24    let mut first_y = None;
25    let mut idle_y = None;
26
27    loop {
28        let mut index = 0;
29        let mut empty = 0;
30
31        while index < 50 {
32            let computer = &mut network[index];
33
34            match computer.run() {
35                State::Output(value) => {
36                    // Loop until we have accumulated a full packet of 3 values.
37                    sent.push(value);
38                    let [address, x, y] = sent[..] else {
39                        continue;
40                    };
41                    sent.clear();
42
43                    if address == 255 {
44                        // Handle part one.
45                        if first_y.is_none() {
46                            first_y = Some(y);
47                        }
48                        nat_x = x;
49                        nat_y = y;
50                    } else {
51                        let destination = &mut network[address as usize];
52                        destination.input(x);
53                        destination.input(y);
54                    }
55                }
56                // Input queue is empty.
57                State::Input => {
58                    empty += 1;
59                    computer.input(-1);
60                }
61                State::Halted => unreachable!(),
62            }
63
64            index += 1;
65        }
66
67        if empty == 50 {
68            if idle_y == Some(nat_y) {
69                break;
70            }
71            idle_y = Some(nat_y);
72
73            let destination = &mut network[0];
74            destination.input(nat_x);
75            destination.input(nat_y);
76        }
77    }
78
79    (first_y.unwrap(), idle_y.unwrap())
80}
81
82pub fn part1(input: &Input) -> i64 {
83    input.0
84}
85
86pub fn part2(input: &Input) -> i64 {
87    input.1
88}