|
@@ -9,17 +9,14 @@ const INPUT: &str = "inputs/11.txt";
|
9
|
9
|
const GRID_SIZE: usize = 300;
|
10
|
10
|
|
11
|
11
|
#[derive(Clone)]
|
12
|
|
-struct Cells([[Option<i8>; GRID_SIZE]; GRID_SIZE]);
|
|
12
|
+struct Cells([[i32; GRID_SIZE + 1]; GRID_SIZE + 1]);
|
13
|
13
|
|
14
|
14
|
impl fmt::Display for Cells {
|
15
|
15
|
#[allow(clippy::write_with_newline)]
|
16
|
16
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
17
|
|
- for x in 0..GRID_SIZE {
|
18
|
|
- for y in 0..GRID_SIZE {
|
19
|
|
- match self.0[x][y] {
|
20
|
|
- Some(power) => write!(f, "{}", power)?,
|
21
|
|
- None => write!(f, ".")?,
|
22
|
|
- }
|
|
17
|
+ for x in 1..=GRID_SIZE {
|
|
18
|
+ for y in 1..=GRID_SIZE {
|
|
19
|
+ write!(f, "{}", self.0[x][y])?;
|
23
|
20
|
}
|
24
|
21
|
write!(f, "\n")?;
|
25
|
22
|
}
|
|
@@ -37,7 +34,7 @@ impl fmt::Debug for Cells {
|
37
|
34
|
#[derive(Debug, Clone)]
|
38
|
35
|
struct Grid {
|
39
|
36
|
serial_number: usize,
|
40
|
|
- cells: Cells,
|
|
37
|
+ sums: Cells,
|
41
|
38
|
}
|
42
|
39
|
|
43
|
40
|
#[derive(Debug, PartialEq, Clone)]
|
|
@@ -52,49 +49,60 @@ pub struct Subsection {
|
52
|
49
|
pub size: usize,
|
53
|
50
|
}
|
54
|
51
|
|
|
52
|
+impl Subsection {
|
|
53
|
+ fn top_left(&self) -> Subsection {
|
|
54
|
+ Subsection {
|
|
55
|
+ coord: Coordinate {
|
|
56
|
+ x: self.coord.x - self.size + 1,
|
|
57
|
+ y: self.coord.y - self.size + 1,
|
|
58
|
+ },
|
|
59
|
+ size: self.size,
|
|
60
|
+ }
|
|
61
|
+ }
|
|
62
|
+}
|
|
63
|
+
|
55
|
64
|
impl Grid {
|
56
|
65
|
fn new(serial_number: usize) -> Grid {
|
57
|
66
|
Grid {
|
58
|
67
|
serial_number,
|
59
|
|
- cells: Cells([[None; GRID_SIZE]; GRID_SIZE]),
|
|
68
|
+ sums: Cells([[0; GRID_SIZE + 1]; GRID_SIZE + 1]),
|
60
|
69
|
}
|
61
|
70
|
}
|
62
|
71
|
|
63
|
|
- fn power_at_cell(&self, coord: &Coordinate) -> i8 {
|
|
72
|
+ fn power_at_cell(&self, coord: &Coordinate) -> i32 {
|
64
|
73
|
let rack_id = coord.x + 10;
|
65
|
74
|
let mut power_level = rack_id * coord.y;
|
66
|
75
|
power_level += self.serial_number;
|
67
|
76
|
power_level *= rack_id;
|
68
|
77
|
power_level = power_level / 100 % 10;
|
69
|
|
- power_level as i8 - 5
|
|
78
|
+ power_level as i32 - 5
|
70
|
79
|
}
|
71
|
80
|
|
72
|
|
- fn power_of_subsection(&mut self, subsection: &Subsection) -> i32 {
|
73
|
|
- let mut power_level: i32 = 0;
|
74
|
|
- let Subsection { coord, size } = subsection;
|
75
|
|
- for x in coord.x..coord.x + size {
|
76
|
|
- for y in coord.y..coord.y + size {
|
77
|
|
- power_level += i32::from(match self.cells.0[x][y] {
|
78
|
|
- Some(power) => power,
|
79
|
|
- None => {
|
80
|
|
- let power = self.power_at_cell(&Coordinate { x, y });
|
81
|
|
- self.cells.0[x][y] = Some(power);
|
82
|
|
- power
|
83
|
|
- }
|
84
|
|
- });
|
|
81
|
+ fn fill_sums(&mut self) {
|
|
82
|
+ for x in 1..=GRID_SIZE {
|
|
83
|
+ for y in 1..=GRID_SIZE {
|
|
84
|
+ let power = self.power_at_cell(&Coordinate { x, y });
|
|
85
|
+ self.sums.0[x][y] = power + self.sums.0[x - 1][y] + self.sums.0[x][y - 1]
|
|
86
|
+ - self.sums.0[x - 1][y - 1];
|
85
|
87
|
}
|
86
|
88
|
}
|
87
|
|
- power_level
|
|
89
|
+ }
|
|
90
|
+
|
|
91
|
+ fn power_of_subsection(&mut self, subsection: &Subsection) -> i32 {
|
|
92
|
+ let Subsection { coord, size } = subsection;
|
|
93
|
+ let &Coordinate { x, y } = coord;
|
|
94
|
+ self.sums.0[x][y] - self.sums.0[x - size][y] - self.sums.0[x][y - size]
|
|
95
|
+ + self.sums.0[x - size][y - size]
|
88
|
96
|
}
|
89
|
97
|
|
90
|
98
|
fn highest_power_subsection(&mut self, size: usize) -> (Subsection, i32) {
|
91
|
99
|
let mut highest_power_subsection = Subsection {
|
92
|
|
- coord: Coordinate { x: 0, y: 0 },
|
|
100
|
+ coord: Coordinate { x: size, y: size },
|
93
|
101
|
size,
|
94
|
102
|
};
|
95
|
103
|
let mut highest_power_level = self.power_of_subsection(&highest_power_subsection);
|
96
|
|
- for x in 0..GRID_SIZE - size {
|
97
|
|
- for y in 0..GRID_SIZE - size {
|
|
104
|
+ for x in size..GRID_SIZE {
|
|
105
|
+ for y in size..GRID_SIZE {
|
98
|
106
|
let subsection = Subsection {
|
99
|
107
|
coord: Coordinate { x, y },
|
100
|
108
|
size,
|
|
@@ -109,7 +117,7 @@ impl Grid {
|
109
|
117
|
}
|
110
|
118
|
}
|
111
|
119
|
}
|
112
|
|
- (highest_power_subsection, highest_power_level)
|
|
120
|
+ (highest_power_subsection.top_left(), highest_power_level)
|
113
|
121
|
}
|
114
|
122
|
}
|
115
|
123
|
|
|
@@ -121,12 +129,14 @@ fn read_serial_number_file(filename: &str) -> Result<usize> {
|
121
|
129
|
pub fn solve_part1() -> Result<Subsection> {
|
122
|
130
|
let serial_number = read_serial_number_file(INPUT)?;
|
123
|
131
|
let mut grid = Grid::new(serial_number);
|
|
132
|
+ grid.fill_sums();
|
124
|
133
|
Ok(grid.highest_power_subsection(3).0)
|
125
|
134
|
}
|
126
|
135
|
|
127
|
136
|
pub fn solve_part2() -> Result<Subsection> {
|
128
|
137
|
let serial_number = read_serial_number_file(INPUT)?;
|
129
|
138
|
let mut grid = Grid::new(serial_number);
|
|
139
|
+ grid.fill_sums();
|
130
|
140
|
let (mut highest_power_subsection, mut highest_power_level) = grid.highest_power_subsection(1);
|
131
|
141
|
|
132
|
142
|
for size in 2..=GRID_SIZE {
|
|
@@ -164,9 +174,10 @@ mod tests {
|
164
|
174
|
#[test]
|
165
|
175
|
fn returns_power_of_subsection() {
|
166
|
176
|
let mut grid = Grid::new(18);
|
|
177
|
+ grid.fill_sums();
|
167
|
178
|
assert_eq!(
|
168
|
179
|
grid.power_of_subsection(&Subsection {
|
169
|
|
- coord: Coordinate { x: 33, y: 45 },
|
|
180
|
+ coord: Coordinate { x: 35, y: 47 },
|
170
|
181
|
size: 3
|
171
|
182
|
}),
|
172
|
183
|
29
|
|
@@ -176,6 +187,7 @@ mod tests {
|
176
|
187
|
#[test]
|
177
|
188
|
fn returns_highest_power_subsection() {
|
178
|
189
|
let mut grid = Grid::new(18);
|
|
190
|
+ grid.fill_sums();
|
179
|
191
|
assert_eq!(
|
180
|
192
|
grid.highest_power_subsection(3),
|
181
|
193
|
(
|