1use super::intcode::*;
11use crate::util::parse::*;
12
13pub fn parse(input: &str) -> Vec<i64> {
14 input.iter_signed().collect()
15}
16
17pub fn part1(input: &[i64]) -> usize {
18 let mut computer = Computer::new(input);
19 let mut blocks = 0;
20
21 while let [_, _, State::Output(t)] = [computer.run(), computer.run(), computer.run()] {
22 if t == 2 {
23 blocks += 1;
24 }
25 }
26
27 blocks
28}
29
30pub fn part2(input: &[i64]) -> i64 {
31 let mut modified = input.to_vec();
32 modified[0] = 2;
33
34 let mut computer = Computer::new(&modified);
35 let mut tiles = Vec::with_capacity(1_000);
36 let mut stride = 0;
37 let mut score = 0;
38 let mut blocks = score;
39 let mut ball: i64 = 0;
40 let mut paddle: i64 = 0;
41
42 loop {
43 let x = match computer.run() {
44 State::Input => {
45 let delta = (ball - paddle).signum();
47 computer.input(delta);
48 continue;
49 }
50 State::Output(x) => x,
51 State::Halted => unreachable!(),
52 };
53 let State::Output(y) = computer.run() else { unreachable!() };
54 let State::Output(t) = computer.run() else { unreachable!() };
55
56 if x < 0 {
57 score = t;
58 if blocks == 0 {
59 break score;
60 }
61 } else {
62 stride = stride.max(x + 1);
63 let index = (stride * y + x) as usize;
64 if index >= tiles.len() {
65 tiles.resize(index + 1, 0);
66 }
67
68 match t {
69 0 if tiles[index] == 2 => blocks -= 1,
70 2 if tiles[index] != 2 => blocks += 1,
71 3 => paddle = x,
72 4 => ball = x,
73 _ => (),
74 }
75
76 tiles[index] = t;
77 }
78
79 draw(&tiles, stride, score, blocks);
82 }
83}
84
85#[cfg(not(feature = "frivolity"))]
86fn draw(_tiles: &[i64], _stride: i64, _score: i64, _blocks: i64) {}
87
88#[cfg(feature = "frivolity")]
89fn draw(tiles: &[i64], stride: i64, score: i64, blocks: i64) {
90 use crate::util::ansi::*;
91 use std::fmt::Write as _;
92 use std::thread::sleep;
93 use std::time::Duration;
94
95 let paddle = tiles.iter().rposition(|&t| t == 3).unwrap_or(tiles.len());
97 if tiles[paddle..].iter().filter(|&&t| t == 1).count() < 3 {
98 return;
99 }
100
101 let s = &mut String::new();
102 let _ = writeln!(s, "{WHITE}{BOLD}Blocks: {blocks}\tScore: {score} {RESET}");
103 let mut y = 0;
104
105 while stride * y < tiles.len() as i64 {
106 for x in 0..stride {
107 let index = (stride * y + x) as usize;
108 let _unused = match tiles[index] {
109 0 => write!(s, " "),
110 1 if y == 0 => write!(s, "{GREEN}_{RESET}"),
111 1 => write!(s, "{GREEN}|{RESET}"),
112 2 => write!(s, "{BLUE}#{RESET}"),
113 3 => write!(s, "{WHITE}{BOLD}={RESET}"),
114 4 => write!(s, "{YELLOW}{BOLD}o{RESET}"),
115 _ => unreachable!(),
116 };
117 }
118 s.push('\n');
119 y += 1;
120 }
121
122 println!("{HOME}{CLEAR}{s}");
123 sleep(Duration::from_millis(20));
124}