Solve 12.1
This commit is contained in:
parent
700fe510c2
commit
1f49f71068
4 changed files with 118 additions and 22 deletions
|
@ -56,7 +56,7 @@ fn check_x_mas(start: IVec2, field: &Field) -> usize {
|
|||
}
|
||||
|
||||
fn count_xmas_at(start: IVec2, field: &Field) -> usize {
|
||||
DIRECTIONS
|
||||
DIRECTIONS8
|
||||
.iter()
|
||||
.filter(|&&dir| check_xmas(start, dir, field))
|
||||
.count()
|
||||
|
@ -69,17 +69,6 @@ fn check_xmas(start: IVec2, direction: IVec2, field: &Field) -> bool {
|
|||
&& field.get(start + direction * 3) == 'S'
|
||||
}
|
||||
|
||||
const DIRECTIONS: [IVec2; 8] = [
|
||||
IVec2::new(1, 0),
|
||||
IVec2::new(1, 1),
|
||||
IVec2::new(0, 1),
|
||||
IVec2::new(-1, 1),
|
||||
IVec2::new(-1, 0),
|
||||
IVec2::new(-1, -1),
|
||||
IVec2::new(0, -1),
|
||||
IVec2::new(1, -1),
|
||||
];
|
||||
|
||||
struct Field {
|
||||
data: Vec<Vec<char>>,
|
||||
}
|
||||
|
|
|
@ -22,15 +22,6 @@ fn part2(input: &str) -> usize {
|
|||
map.trailheads().map(|t| map.distinct_trails(t)).sum()
|
||||
}
|
||||
|
||||
fn directions() -> [IVec2; 4] {
|
||||
[
|
||||
IVec2::new(1, 0),
|
||||
IVec2::new(-1, 0),
|
||||
IVec2::new(0, 1),
|
||||
IVec2::new(0, -1),
|
||||
]
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Map {
|
||||
height: HashMap<IVec2, i64>,
|
||||
|
@ -67,7 +58,7 @@ impl Map {
|
|||
}
|
||||
|
||||
fn climb_up(&self, from: IVec2, from_height: i64) -> Vec<IVec2> {
|
||||
directions()
|
||||
DIRECTIONS4
|
||||
.into_iter()
|
||||
.filter_map(|dir| {
|
||||
let pos = from + dir;
|
||||
|
|
95
src/bin/12.rs
Normal file
95
src/bin/12.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
use aoc::*;
|
||||
use glam::IVec2;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::iter;
|
||||
|
||||
const INPUT: &str = include_str!("../../input/12");
|
||||
|
||||
fn main() {
|
||||
assert_example!(part1, "12-test", 140);
|
||||
println!("Part 1: {}", part1(INPUT));
|
||||
assert_example!(part2, "12-test", 0);
|
||||
println!("Part 2: {}", part2(INPUT));
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> usize {
|
||||
parse_regions(input).iter().map(Region::fence_cost).sum()
|
||||
}
|
||||
fn part2(_input: &str) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn parse_regions(input: &str) -> Vec<Region> {
|
||||
let mut map = parse_map(input);
|
||||
let mut regions = Vec::new();
|
||||
loop {
|
||||
let Some((&start_pos, &plant)) = map.iter().next() else {
|
||||
break;
|
||||
};
|
||||
let mut visited = HashSet::new();
|
||||
let mut region = Vec::new();
|
||||
let mut check = vec![start_pos];
|
||||
let mut perimeter = 0;
|
||||
while let Some(next) = check.pop() {
|
||||
if visited.contains(&next) {
|
||||
continue;
|
||||
}
|
||||
visited.insert(next);
|
||||
let Some(&p) = map.get(&next) else { continue };
|
||||
if p != plant {
|
||||
continue;
|
||||
}
|
||||
|
||||
region.push(next);
|
||||
map.remove(&next);
|
||||
|
||||
// Adjust perimeter
|
||||
let empty_sides = DIRECTIONS4
|
||||
.into_iter()
|
||||
.map(|dir| dir + next)
|
||||
.filter(|pos| !region.contains(pos))
|
||||
.count();
|
||||
let taken_sides = 4 - empty_sides;
|
||||
perimeter = perimeter + empty_sides - taken_sides;
|
||||
|
||||
let neighbors = DIRECTIONS4.into_iter().map(|dir| dir + next);
|
||||
check.extend(neighbors);
|
||||
}
|
||||
regions.push(Region {
|
||||
_plant: plant,
|
||||
fields: region,
|
||||
perimeter,
|
||||
});
|
||||
}
|
||||
regions
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Region {
|
||||
_plant: char,
|
||||
fields: Vec<IVec2>,
|
||||
perimeter: usize,
|
||||
}
|
||||
|
||||
impl Region {
|
||||
fn area(&self) -> usize {
|
||||
self.fields.len()
|
||||
}
|
||||
|
||||
fn fence_cost(&self) -> usize {
|
||||
self.perimeter * self.area()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_map(input: &str) -> HashMap<IVec2, char> {
|
||||
// TODO Reading a grid with coordinates should be a helper function.
|
||||
input
|
||||
.lines()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| line.chars().enumerate().zip(iter::repeat(y)))
|
||||
.map(|((x, c), y)| {
|
||||
let pos = IVec2::new(x as i32, y as i32);
|
||||
(pos, c)
|
||||
})
|
||||
.collect()
|
||||
}
|
21
src/lib.rs
21
src/lib.rs
|
@ -1,5 +1,6 @@
|
|||
//! This library contains useful helper functions that may be useful in several problems.
|
||||
|
||||
use glam::IVec2;
|
||||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
ops::{Div, Mul, Rem},
|
||||
|
@ -106,3 +107,23 @@ macro_rules! assert_example {
|
|||
)
|
||||
};
|
||||
}
|
||||
|
||||
/// 4 directions. Start pointing right and go CCW.
|
||||
pub const DIRECTIONS4: [IVec2; 4] = [
|
||||
IVec2::new(1, 0),
|
||||
IVec2::new(0, 1),
|
||||
IVec2::new(-1, 0),
|
||||
IVec2::new(0, -1),
|
||||
];
|
||||
|
||||
/// 8 directions. Start pointing right and go CCW.
|
||||
pub const DIRECTIONS8: [IVec2; 8] = [
|
||||
IVec2::new(1, 0),
|
||||
IVec2::new(1, 1),
|
||||
IVec2::new(0, 1),
|
||||
IVec2::new(-1, 1),
|
||||
IVec2::new(-1, 0),
|
||||
IVec2::new(-1, -1),
|
||||
IVec2::new(0, -1),
|
||||
IVec2::new(1, -1),
|
||||
];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue