Solve 12
This commit is contained in:
parent
44f9b238f7
commit
271d764144
1 changed files with 50 additions and 4 deletions
|
@ -1,5 +1,6 @@
|
||||||
use aoc::*;
|
use aoc::*;
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
|
use itertools::Itertools;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
|
@ -8,15 +9,19 @@ const INPUT: &str = include_str!("../../input/12");
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_example!(part1, "12-test", 140);
|
assert_example!(part1, "12-test", 140);
|
||||||
println!("Part 1: {}", part1(INPUT));
|
println!("Part 1: {}", part1(INPUT));
|
||||||
assert_example!(part2, "12-test", 0);
|
assert_example!(part2, "12-test", 80);
|
||||||
println!("Part 2: {}", part2(INPUT));
|
println!("Part 2: {}", part2(INPUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(input: &str) -> usize {
|
fn part1(input: &str) -> usize {
|
||||||
parse_regions(input).iter().map(Region::fence_cost).sum()
|
parse_regions(input).iter().map(Region::fence_cost).sum()
|
||||||
}
|
}
|
||||||
fn part2(_input: &str) -> usize {
|
|
||||||
0
|
fn part2(input: &str) -> usize {
|
||||||
|
parse_regions(input)
|
||||||
|
.iter()
|
||||||
|
.map(Region::bulk_fence_cost)
|
||||||
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_regions(input: &str) -> Vec<Region> {
|
fn parse_regions(input: &str) -> Vec<Region> {
|
||||||
|
@ -79,10 +84,51 @@ impl Region {
|
||||||
fn fence_cost(&self) -> usize {
|
fn fence_cost(&self) -> usize {
|
||||||
self.perimeter * self.area()
|
self.perimeter * self.area()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bulk_fence_cost(&self) -> usize {
|
||||||
|
self.corners() * self.area()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Detect corners by moving a 2x2 window over the region and checking the shape.
|
||||||
|
/// A region has as many corners as edges.
|
||||||
|
fn corners(&self) -> usize {
|
||||||
|
let min = self.fields.iter().fold(IVec2::ZERO, |acc, &x| acc.min(x)) - IVec2::ONE;
|
||||||
|
let max = self.fields.iter().fold(IVec2::ZERO, |acc, &x| acc.max(x));
|
||||||
|
|
||||||
|
let clockwise = [
|
||||||
|
IVec2::ZERO,
|
||||||
|
IVec2::new(1, 0),
|
||||||
|
IVec2::new(1, 1),
|
||||||
|
IVec2::new(0, 1),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut corners = 0;
|
||||||
|
|
||||||
|
for y in min.y..=max.y {
|
||||||
|
for x in min.x..=max.x {
|
||||||
|
let p = IVec2::new(x, y);
|
||||||
|
let pattern = clockwise
|
||||||
|
.iter()
|
||||||
|
.map(|dir| p + dir)
|
||||||
|
.map(|p| self.fields.contains(&p))
|
||||||
|
.collect_vec();
|
||||||
|
let count = pattern.iter().filter(|b| **b).count();
|
||||||
|
match count {
|
||||||
|
0 | 4 => (),
|
||||||
|
1 | 3 => corners += 1,
|
||||||
|
2 if pattern == [true, false, true, false] => corners += 2,
|
||||||
|
2 if pattern == [false, true, false, true] => corners += 2,
|
||||||
|
2 => (),
|
||||||
|
other => unreachable!("should not have {other} elements when checking corners"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
corners
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_map(input: &str) -> HashMap<IVec2, char> {
|
fn parse_map(input: &str) -> HashMap<IVec2, char> {
|
||||||
// TODO Reading a grid with coordinates should be a helper function.
|
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue