Speed up day 11 with summed area table

This commit is contained in:
Tyler Hallada 2019-08-04 18:55:17 -04:00
parent 55c949f796
commit fa882266a6

View File

@ -9,17 +9,14 @@ const INPUT: &str = "inputs/11.txt";
const GRID_SIZE: usize = 300; const GRID_SIZE: usize = 300;
#[derive(Clone)] #[derive(Clone)]
struct Cells([[Option<i8>; GRID_SIZE]; GRID_SIZE]); struct Cells([[i32; GRID_SIZE + 1]; GRID_SIZE + 1]);
impl fmt::Display for Cells { impl fmt::Display for Cells {
#[allow(clippy::write_with_newline)] #[allow(clippy::write_with_newline)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for x in 0..GRID_SIZE { for x in 1..=GRID_SIZE {
for y in 0..GRID_SIZE { for y in 1..=GRID_SIZE {
match self.0[x][y] { write!(f, "{}", self.0[x][y])?;
Some(power) => write!(f, "{}", power)?,
None => write!(f, ".")?,
}
} }
write!(f, "\n")?; write!(f, "\n")?;
} }
@ -37,7 +34,7 @@ impl fmt::Debug for Cells {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Grid { struct Grid {
serial_number: usize, serial_number: usize,
cells: Cells, sums: Cells,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -52,49 +49,60 @@ pub struct Subsection {
pub size: usize, pub size: usize,
} }
impl Subsection {
fn top_left(&self) -> Subsection {
Subsection {
coord: Coordinate {
x: self.coord.x - self.size + 1,
y: self.coord.y - self.size + 1,
},
size: self.size,
}
}
}
impl Grid { impl Grid {
fn new(serial_number: usize) -> Grid { fn new(serial_number: usize) -> Grid {
Grid { Grid {
serial_number, serial_number,
cells: Cells([[None; GRID_SIZE]; GRID_SIZE]), sums: Cells([[0; GRID_SIZE + 1]; GRID_SIZE + 1]),
} }
} }
fn power_at_cell(&self, coord: &Coordinate) -> i8 { fn power_at_cell(&self, coord: &Coordinate) -> i32 {
let rack_id = coord.x + 10; let rack_id = coord.x + 10;
let mut power_level = rack_id * coord.y; let mut power_level = rack_id * coord.y;
power_level += self.serial_number; power_level += self.serial_number;
power_level *= rack_id; power_level *= rack_id;
power_level = power_level / 100 % 10; power_level = power_level / 100 % 10;
power_level as i8 - 5 power_level as i32 - 5
}
fn fill_sums(&mut self) {
for x in 1..=GRID_SIZE {
for y in 1..=GRID_SIZE {
let power = self.power_at_cell(&Coordinate { x, y });
self.sums.0[x][y] = power + self.sums.0[x - 1][y] + self.sums.0[x][y - 1]
- self.sums.0[x - 1][y - 1];
}
}
} }
fn power_of_subsection(&mut self, subsection: &Subsection) -> i32 { fn power_of_subsection(&mut self, subsection: &Subsection) -> i32 {
let mut power_level: i32 = 0;
let Subsection { coord, size } = subsection; let Subsection { coord, size } = subsection;
for x in coord.x..coord.x + size { let &Coordinate { x, y } = coord;
for y in coord.y..coord.y + size { self.sums.0[x][y] - self.sums.0[x - size][y] - self.sums.0[x][y - size]
power_level += i32::from(match self.cells.0[x][y] { + self.sums.0[x - size][y - size]
Some(power) => power,
None => {
let power = self.power_at_cell(&Coordinate { x, y });
self.cells.0[x][y] = Some(power);
power
}
});
}
}
power_level
} }
fn highest_power_subsection(&mut self, size: usize) -> (Subsection, i32) { fn highest_power_subsection(&mut self, size: usize) -> (Subsection, i32) {
let mut highest_power_subsection = Subsection { let mut highest_power_subsection = Subsection {
coord: Coordinate { x: 0, y: 0 }, coord: Coordinate { x: size, y: size },
size, size,
}; };
let mut highest_power_level = self.power_of_subsection(&highest_power_subsection); let mut highest_power_level = self.power_of_subsection(&highest_power_subsection);
for x in 0..GRID_SIZE - size { for x in size..GRID_SIZE {
for y in 0..GRID_SIZE - size { for y in size..GRID_SIZE {
let subsection = Subsection { let subsection = Subsection {
coord: Coordinate { x, y }, coord: Coordinate { x, y },
size, size,
@ -109,7 +117,7 @@ impl Grid {
} }
} }
} }
(highest_power_subsection, highest_power_level) (highest_power_subsection.top_left(), highest_power_level)
} }
} }
@ -121,12 +129,14 @@ fn read_serial_number_file(filename: &str) -> Result<usize> {
pub fn solve_part1() -> Result<Subsection> { pub fn solve_part1() -> Result<Subsection> {
let serial_number = read_serial_number_file(INPUT)?; let serial_number = read_serial_number_file(INPUT)?;
let mut grid = Grid::new(serial_number); let mut grid = Grid::new(serial_number);
grid.fill_sums();
Ok(grid.highest_power_subsection(3).0) Ok(grid.highest_power_subsection(3).0)
} }
pub fn solve_part2() -> Result<Subsection> { pub fn solve_part2() -> Result<Subsection> {
let serial_number = read_serial_number_file(INPUT)?; let serial_number = read_serial_number_file(INPUT)?;
let mut grid = Grid::new(serial_number); let mut grid = Grid::new(serial_number);
grid.fill_sums();
let (mut highest_power_subsection, mut highest_power_level) = grid.highest_power_subsection(1); let (mut highest_power_subsection, mut highest_power_level) = grid.highest_power_subsection(1);
for size in 2..=GRID_SIZE { for size in 2..=GRID_SIZE {
@ -164,9 +174,10 @@ mod tests {
#[test] #[test]
fn returns_power_of_subsection() { fn returns_power_of_subsection() {
let mut grid = Grid::new(18); let mut grid = Grid::new(18);
grid.fill_sums();
assert_eq!( assert_eq!(
grid.power_of_subsection(&Subsection { grid.power_of_subsection(&Subsection {
coord: Coordinate { x: 33, y: 45 }, coord: Coordinate { x: 35, y: 47 },
size: 3 size: 3
}), }),
29 29
@ -176,6 +187,7 @@ mod tests {
#[test] #[test]
fn returns_highest_power_subsection() { fn returns_highest_power_subsection() {
let mut grid = Grid::new(18); let mut grid = Grid::new(18);
grid.fill_sums();
assert_eq!( assert_eq!(
grid.highest_power_subsection(3), grid.highest_power_subsection(3),
( (