1use super::intcode::*;
5use crate::util::hash::*;
6use crate::util::parse::*;
7use crate::util::point::*;
8
9pub fn parse(input: &str) -> Vec<i64> {
10 input.iter_signed().collect()
11}
12
13pub fn part1(input: &[i64]) -> usize {
14 paint(input, 0).len()
15}
16
17pub fn part2(input: &[i64]) -> String {
18 let hull = paint(input, 1);
19
20 let panels: Vec<_> = hull.iter().filter(|&(_, &v)| v == 1).map(|(&k, _)| k).collect();
22
23 let mut x1 = i32::MAX;
25 let mut x2 = i32::MIN;
26 let mut y1 = i32::MAX;
27 let mut y2 = i32::MIN;
28
29 for &point in &panels {
30 x1 = x1.min(point.x);
31 x2 = x2.max(point.x);
32 y1 = y1.min(point.y);
33 y2 = y2.max(point.y);
34 }
35
36 let width = (x2 - x1 + 1) as usize;
38 let height = (y2 - y1 + 1) as usize;
39 let offset = Point::new(x1, y1);
40 let mut image = vec!['.'; width * height];
41
42 for &point in &panels {
43 let adjusted = point - offset;
44 let index = (width * adjusted.y as usize) + (adjusted.x as usize);
45 image[index] = '#';
46 }
47
48 let mut result = image
50 .chunks_exact(width)
51 .map(|row| row.iter().collect())
52 .collect::<Vec<String>>()
53 .join("\n");
54 result.insert(0, '\n');
55 result
56}
57
58fn paint(input: &[i64], initial: i64) -> FastMap<Point, i64> {
59 let mut computer = Computer::new(input);
60 let mut position = ORIGIN;
61 let mut direction = UP;
62 let mut hull = FastMap::with_capacity(5_000);
63
64 hull.insert(position, initial);
65
66 loop {
67 let panel = hull.get(&position).unwrap_or(&0);
68 computer.input(*panel);
69
70 match computer.run() {
71 State::Output(color) => {
72 hull.insert(position, color);
73 }
74 _ => break,
75 }
76
77 match computer.run() {
78 State::Output(next) => {
79 direction =
80 if next == 0 { direction.counter_clockwise() } else { direction.clockwise() };
81 position += direction;
82 }
83 _ => break,
84 }
85 }
86
87 hull
88}