1use crate::util::parse::*;
9use crate::util::thread::*;
10use std::sync::Mutex;
11
12pub struct Result {
13 x: usize,
14 y: usize,
15 size: usize,
16 power: i32,
17}
18
19struct Shared {
20 sat: Vec<i32>,
21 mutex: Mutex<Vec<Result>>,
22}
23
24pub fn parse(input: &str) -> Vec<Result> {
25 let grid_serial_number: i32 = input.signed();
26
27 let mut sat = vec![0; 301 * 301];
29
30 for y in 1..301 {
31 for x in 1..301 {
32 let rack_id = x + 10;
33
34 let mut power_level = rack_id * y;
35 power_level += grid_serial_number;
36 power_level *= rack_id;
37 power_level = (power_level / 100) % 10;
38 power_level -= 5;
39
40 let index = (301 * y + x) as usize;
41 sat[index] = power_level + sat[index - 1] + sat[index - 301] - sat[index - 302];
42 }
43 }
44
45 let items: Vec<_> = (1..301).collect();
48 let shared = Shared { sat, mutex: Mutex::new(Vec::new()) };
49 spawn_parallel_iterator(&items, |iter| worker(&shared, iter));
50 shared.mutex.into_inner().unwrap()
51}
52
53pub fn part1(input: &[Result]) -> String {
54 let Result { x, y, .. } = input.iter().find(|r| r.size == 3).unwrap();
55 format!("{x},{y}")
56}
57
58pub fn part2(input: &[Result]) -> String {
59 let Result { x, y, size, .. } = input.iter().max_by_key(|r| r.power).unwrap();
60 format!("{x},{y},{size}")
61}
62
63fn worker(shared: &Shared, iter: ParIter<'_, usize>) {
64 let result: Vec<_> = iter
65 .map(|&size| {
66 let (power, x, y) = square(&shared.sat, size);
67 Result { x, y, size, power }
68 })
69 .collect();
70
71 shared.mutex.lock().unwrap().extend(result);
72}
73
74fn square(sat: &[i32], size: usize) -> (i32, usize, usize) {
76 let mut max_power = i32::MIN;
77 let mut max_x = 0;
78 let mut max_y = 0;
79
80 for y in size..301 {
81 for x in size..301 {
82 let index = 301 * y + x;
83 let power =
84 sat[index] - sat[index - size] - sat[index - 301 * size] + sat[index - 302 * size];
85
86 if power > max_power {
87 max_power = power;
88 max_x = x - size + 1;
89 max_y = y - size + 1;
90 }
91 }
92 }
93
94 (max_power, max_x, max_y)
95}