generated from janezicmatej/aoc-template
solution: day 21
This commit is contained in:
parent
0000038000
commit
0000039019
|
@ -0,0 +1,11 @@
|
||||||
|
...........
|
||||||
|
.....###.#.
|
||||||
|
.###.##..#.
|
||||||
|
..#.#...#..
|
||||||
|
....#.#....
|
||||||
|
.##..S####.
|
||||||
|
.##..#...#.
|
||||||
|
.......##..
|
||||||
|
.##.#.####.
|
||||||
|
.##..##.##.
|
||||||
|
...........
|
|
@ -0,0 +1,106 @@
|
||||||
|
use std::{collections::HashSet, usize};
|
||||||
|
|
||||||
|
fn parse_input(input: &str) -> (Vec<Vec<u8>>, (isize, isize)) {
|
||||||
|
let mut grid: Vec<_> = input.lines().map(|x| x.as_bytes().to_vec()).collect();
|
||||||
|
|
||||||
|
let start = grid
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(y, item)| item.iter().enumerate().map(move |(x, item)| (x, y, *item)))
|
||||||
|
.find_map(|(x, y, s)| if s == b'S' { Some((y, x)) } else { None })
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
grid[start.0][start.1] = b'.';
|
||||||
|
|
||||||
|
(grid, (start.0 as isize, start.1 as isize))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_return_at(
|
||||||
|
grid: &[Vec<u8>],
|
||||||
|
start: (isize, isize),
|
||||||
|
mut returns: Vec<usize>,
|
||||||
|
can_cycle: bool,
|
||||||
|
) -> Vec<usize> {
|
||||||
|
returns.sort_by(|a, b| b.cmp(a));
|
||||||
|
|
||||||
|
let h = grid.len() as isize;
|
||||||
|
let w = grid[0].len() as isize;
|
||||||
|
|
||||||
|
let invalid_indexing = |y, x| y < 0 || y >= h || x < 0 || x >= w;
|
||||||
|
|
||||||
|
let mut results = Vec::new();
|
||||||
|
let length = returns[0];
|
||||||
|
let mut next = returns.pop().unwrap();
|
||||||
|
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
visited.insert(start);
|
||||||
|
|
||||||
|
for i in 1..=length {
|
||||||
|
let mut new_visited = HashSet::new();
|
||||||
|
|
||||||
|
for (y, x) in visited.iter() {
|
||||||
|
for (dy, dx) in [(1, 0), (0, 1), (-1, 0), (0, -1)] {
|
||||||
|
let (ny, nx) = (y + dy, x + dx);
|
||||||
|
|
||||||
|
if !can_cycle && invalid_indexing(ny, nx) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (cy, cx) = (ny.rem_euclid(h) as usize, nx.rem_euclid(w) as usize);
|
||||||
|
|
||||||
|
if grid[cy][cx] == b'.' {
|
||||||
|
new_visited.insert((ny, nx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visited = new_visited;
|
||||||
|
|
||||||
|
if i == next {
|
||||||
|
results.push(visited.len());
|
||||||
|
if !returns.is_empty() {
|
||||||
|
next = returns.pop().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_one(input: &str) -> Option<usize> {
|
||||||
|
let (grid, start) = parse_input(input);
|
||||||
|
let result = walk_return_at(&grid, start, vec![64], false);
|
||||||
|
|
||||||
|
Some(result[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part_two(input: &str) -> Option<usize> {
|
||||||
|
let (grid, start) = parse_input(input);
|
||||||
|
|
||||||
|
let h = grid.len();
|
||||||
|
let s = start.0 as usize;
|
||||||
|
|
||||||
|
let result = walk_return_at(&grid, start, vec![s, s + h, s + 2 * h], true);
|
||||||
|
|
||||||
|
let a = (result[2] - 2 * result[1] + result[0]) / 2;
|
||||||
|
let b = (result[1] - result[0]) - a;
|
||||||
|
let c = result[0];
|
||||||
|
|
||||||
|
let x = 26501365 / h;
|
||||||
|
|
||||||
|
Some(a * x * x + b * x + c)
|
||||||
|
}
|
||||||
|
|
||||||
|
aoc::solution!(21);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_part_one() {
|
||||||
|
assert_eq!(
|
||||||
|
part_one(&aoc::template::read_file("examples", 21)),
|
||||||
|
Some(42)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue