Browse Source

Speed up day 11 with summed area table

Tyler Hallada 4 years ago
parent
commit
fa882266a6
1 changed files with 42 additions and 30 deletions
  1. 42 30
      src/day11.rs

+ 42 - 30
src/day11.rs

@@ -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
             (