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