1
0
Fork 0

day21 solution

main
Andrew Coleman 2024-01-12 13:50:22 -05:00
parent 59e06d73eb
commit 562cd63d87
2 changed files with 129 additions and 0 deletions

128
2023/src/day21.rs Normal file
View File

@ -0,0 +1,128 @@
use aoc_runner_derive::{aoc, aoc_generator};
use std::collections::{HashMap, VecDeque};
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
struct Point(usize, usize);
type Map = [[char; 131]; 131];
#[aoc_generator(day21)]
fn parse(input: &str) -> (Point, Map) {
let mut m = [['#'; 131]; 131];
let mut start: Point = Point(0, 0);
for (x, line) in input.lines().enumerate() {
if line.is_empty() {
continue;
}
for (y, t) in line.chars().enumerate() {
match t {
'.' => m[x][y] = '.',
'#' => {}
'S' => {
start.0 = x;
start.1 = y;
m[x][y] = '.';
}
n @ _ => panic!("bad map char {}", n),
}
}
}
(start, m)
}
fn infinite_step(start: &Point, map: &Map) -> HashMap<Point, usize> {
let mut visited: HashMap<Point, usize> = HashMap::new();
let mut frontier: VecDeque<(Point, usize)> = VecDeque::new();
frontier.push_back((*start, 0));
while let Some((cur, dist)) = frontier.pop_front() {
if visited.contains_key(&cur) {
continue;
}
visited.insert(cur, dist);
let x = cur.0;
let y = cur.1;
if x > 0 && map[x - 1][y] == '.' {
let p = Point(x - 1, y);
if !visited.contains_key(&p) {
frontier.push_back((p, dist + 1));
}
}
if x < map.len() - 1 && map[x + 1][y as usize] == '.' {
let p = Point(x + 1, y);
if !visited.contains_key(&p) {
frontier.push_back((p, dist + 1));
}
}
if y > 0 && map[x][y - 1] == '.' {
let p = Point(x, y - 1);
if !visited.contains_key(&p) {
frontier.push_back((p, dist + 1));
}
}
if y < map[x].len() - 1 && map[x][y + 1] == '.' {
let p = Point(x, y + 1);
if !visited.contains_key(&p) {
frontier.push_back((p, dist + 1));
}
}
}
visited
}
#[aoc(day21, part1)]
fn part1(input: &(Point, Map)) -> usize {
let visited = infinite_step(&input.0, &input.1);
visited
.values()
.filter(|t| **t <= 64 && **t % 2 == 0)
.count()
}
#[aoc(day21, part2)]
fn part2(input: &(Point, Map)) -> usize {
let visited = infinite_step(&input.0, &input.1);
let even_corners = visited
.values()
.filter(|v| **v % 2 == 0 && **v > 65)
.count();
let odd_corners = visited
.values()
.filter(|v| **v % 2 == 1 && **v > 65)
.count();
let even_full = visited.values().filter(|v| **v % 2 == 0).count();
let odd_full = visited.values().filter(|v| **v % 2 == 1).count();
let n = ((26501365 - (input.1.len() / 2)) / input.1.len()) as usize;
assert_eq!(n, 202300);
((n + 1) * (n + 1)) * odd_full + (n * n) * even_full - (n + 1) * odd_corners + n * even_corners
}
#[cfg(test)]
mod tests {
use super::*;
const SAMPLE_DATA: &'static str = r#"...........
.....###.#.
.###.##..#.
..#.#...#..
....#.#....
.##..S####.
.##..#...#.
.......##..
.##.#.####.
.##..##.##.
..........."#;
#[test]
fn sample_data() {
let input = parse(&SAMPLE_DATA);
assert_eq!(part1(&input), 42);
}
}

View File

@ -20,5 +20,6 @@ mod day17;
mod day18;
mod day19;
mod day20;
mod day21;
aoc_lib! { year = 2023 }