day21 solution
parent
59e06d73eb
commit
562cd63d87
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,5 +20,6 @@ mod day17;
|
||||||
mod day18;
|
mod day18;
|
||||||
mod day19;
|
mod day19;
|
||||||
mod day20;
|
mod day20;
|
||||||
|
mod day21;
|
||||||
|
|
||||||
aoc_lib! { year = 2023 }
|
aoc_lib! { year = 2023 }
|
||||||
|
|
Loading…
Reference in New Issue