day12: optimization and cleanup
This commit is contained in:
parent
a56fc933c9
commit
c213bbbc27
67
src/day12.rs
67
src/day12.rs
@ -18,26 +18,28 @@ impl From<&[u8]> for Farm {
|
|||||||
impl Farm {
|
impl Farm {
|
||||||
fn compute_region(&self, pos: &Coord2d, visited: &mut Grid<bool>) -> (u64, u64) {
|
fn compute_region(&self, pos: &Coord2d, visited: &mut Grid<bool>) -> (u64, u64) {
|
||||||
let our_plant = self.map.get(pos).unwrap();
|
let our_plant = self.map.get(pos).unwrap();
|
||||||
let mut perimeter = 0;
|
|
||||||
let mut area = 1;
|
|
||||||
|
|
||||||
visited.set(pos, true);
|
visited.set(pos, true);
|
||||||
|
|
||||||
for adj in [(-1i64, 0i64), (1, 0), (0, -1), (0, 1)].map(|ofs| pos + ofs) {
|
[(-1i64, 0i64), (1, 0), (0, -1), (0, 1)]
|
||||||
match self.map.get(&adj) {
|
.map(|ofs| pos + ofs)
|
||||||
Some(plant) if plant == our_plant => {
|
.iter()
|
||||||
if visited.get(&adj) == Some(false) {
|
.fold((1, 0), |(area, perimeter), adj| {
|
||||||
// add the perimeter of the growth from there if not visited yet
|
match self.map.get(adj) {
|
||||||
let (n_area, n_perimeter) = self.compute_region(&adj, visited);
|
Some(plant) if plant == our_plant => {
|
||||||
area += n_area;
|
if visited.get(adj) == Some(false) {
|
||||||
perimeter += n_perimeter;
|
// add the perimeter of the growth from there if not visited yet
|
||||||
|
let (add_area, add_perimeter) = self.compute_region(&adj, visited);
|
||||||
|
(area + add_area, perimeter + add_perimeter)
|
||||||
|
} else {
|
||||||
|
(area, perimeter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some(_) | None => (area, perimeter + 1),
|
||||||
}
|
}
|
||||||
Some(_) | None => perimeter += 1,
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
(area, perimeter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regions_cost(&self) -> u64 {
|
fn regions_cost(&self) -> u64 {
|
||||||
let mut visited = Grid::with_shape(self.map.width(), self.map.height(), false);
|
let mut visited = Grid::with_shape(self.map.width(), self.map.height(), false);
|
||||||
let mut cost = 0;
|
let mut cost = 0;
|
||||||
@ -61,9 +63,10 @@ impl Farm {
|
|||||||
cost
|
cost
|
||||||
}
|
}
|
||||||
fn count_corners(&self, pos: &Coord2d) -> u64 {
|
fn count_corners(&self, pos: &Coord2d) -> u64 {
|
||||||
// A
|
// NOTE: Iterating twice is faster than combining conditions in one pass
|
||||||
// AAA has 4 inside corners (pos at centre). check that AA A's exist and B doesn't for each rotation
|
// BAB
|
||||||
// A AB
|
// AAA has 4 inside corners (pos at centre). check that for AA A's exist and B doesn't for each rotation
|
||||||
|
// BAB AB
|
||||||
let our_plant = self.map.get(pos);
|
let our_plant = self.map.get(pos);
|
||||||
let inside_corners = [(1i64, 1i64), (-1, 1), (1, -1), (-1, -1)]
|
let inside_corners = [(1i64, 1i64), (-1, 1), (1, -1), (-1, -1)]
|
||||||
.iter()
|
.iter()
|
||||||
@ -73,6 +76,9 @@ impl Farm {
|
|||||||
&& self.map.get(&(pos + (0, inside_corner.1))) == our_plant
|
&& self.map.get(&(pos + (0, inside_corner.1))) == our_plant
|
||||||
})
|
})
|
||||||
.count();
|
.count();
|
||||||
|
// BBB
|
||||||
|
// BAB has 4 outside corners (pos at centre). check that for AB the B are both not equal to A for each rot
|
||||||
|
// BBB BB B
|
||||||
let outside_corners = [(1i64, 1i64), (-1, 1), (1, -1), (-1, -1)]
|
let outside_corners = [(1i64, 1i64), (-1, 1), (1, -1), (-1, -1)]
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|outside_corner| {
|
.filter(|outside_corner| {
|
||||||
@ -84,25 +90,24 @@ impl Farm {
|
|||||||
}
|
}
|
||||||
fn region_corners(&self, pos: &Coord2d, visited: &mut Grid<bool>) -> (u64, u64) {
|
fn region_corners(&self, pos: &Coord2d, visited: &mut Grid<bool>) -> (u64, u64) {
|
||||||
let our_plant = self.map.get(pos).unwrap();
|
let our_plant = self.map.get(pos).unwrap();
|
||||||
let mut area = 1;
|
|
||||||
let mut corners = self.count_corners(pos);
|
|
||||||
|
|
||||||
visited.set(pos, true);
|
visited.set(pos, true);
|
||||||
|
|
||||||
for adj in [(-1i64, 0i64), (1, 0), (0, -1), (0, 1)].map(|ofs| pos + ofs) {
|
[(-1i64, 0i64), (1, 0), (0, -1), (0, 1)]
|
||||||
match self.map.get(&adj) {
|
.map(|ofs| pos + ofs)
|
||||||
Some(plant) if plant == our_plant => {
|
.iter()
|
||||||
if visited.get(&adj) == Some(false) {
|
.fold((1, self.count_corners(pos)), |(area, corners), adj| {
|
||||||
// add the perimeter of the growth from there if not visited yet
|
match self.map.get(adj) {
|
||||||
let (n_area, n_corners) = self.region_corners(&adj, visited);
|
Some(plant) if plant == our_plant => {
|
||||||
area += n_area;
|
if visited.get(adj) == Some(false) {
|
||||||
corners += n_corners;
|
// add the perimeter of the growth from there if not visited yet
|
||||||
|
let (n_area, n_corners) = self.region_corners(&adj, visited);
|
||||||
|
(area+n_area, corners+n_corners)
|
||||||
|
} else { (area, corners) }
|
||||||
}
|
}
|
||||||
|
Some(_) | None => { (area, corners) }
|
||||||
}
|
}
|
||||||
Some(_) | None => {}
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
(area, corners)
|
|
||||||
}
|
}
|
||||||
fn regions_discount_cost(&self) -> u64 {
|
fn regions_discount_cost(&self) -> u64 {
|
||||||
let mut visited = Grid::with_shape(self.map.width(), self.map.height(), false);
|
let mut visited = Grid::with_shape(self.map.width(), self.map.height(), false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user