1
0
Fork 0

day(21): add solution

Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
Matej Focko 2024-07-06 22:17:02 +02:00
parent b6381d38d7
commit 45603e36bf
Signed by: mfocko
SSH key fingerprint: SHA256:5YXD7WbPuK60gxnG6DjAwJiS9+swoWj33/HFu8g8JVo
2 changed files with 122 additions and 0 deletions

11
samples/day21.txt Normal file
View file

@ -0,0 +1,11 @@
...........
.....###.#.
.###.##..#.
..#.#...#..
....#.#....
.##..S####.
.##..#...#.
.......##..
.##.#.####.
.##..##.##.
...........

111
src/bin/day21.rs Normal file
View file

@ -0,0 +1,111 @@
use std::collections::HashSet;
use aoc_2023::*;
use itertools::iproduct;
type Position = Vector2D<isize>;
lazy_static! {
static ref DIRECTIONS: Vec<Position> = vec![
Position::new(0, 1),
Position::new(0, -1),
Position::new(1, 0),
Position::new(-1, 0),
];
}
const WIDTH: isize = 131;
fn _mod(n: isize, m: isize) -> isize {
(m + (n % m)) % m
}
type Output1 = usize;
type Output2 = f64;
struct Steps<'a> {
plots: &'a HashSet<Position>,
positions: HashSet<Position>,
}
impl<'a> Steps<'a> {
fn new(plots: &'a HashSet<Position>) -> Self {
Self {
plots,
positions: HashSet::from([Position::new(65, 65)]),
}
}
fn move_gardener(&mut self) {
let mut next_positions = HashSet::new();
for (&pos, &dir) in iproduct!(self.positions.iter(), DIRECTIONS.iter()) {
let next_pos = pos + dir;
let cropped = Position::new(_mod(next_pos.x(), WIDTH), _mod(next_pos.y(), WIDTH));
if self.plots.contains(&cropped) {
next_positions.insert(next_pos);
}
}
self.positions = next_positions;
}
}
impl<'a> Iterator for Steps<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
let current = self.positions.len();
self.move_gardener();
Some(current)
}
}
struct Day21 {
plots: HashSet<Position>,
}
impl Solution<Output1, Output2> for Day21 {
fn new<P: AsRef<Path>>(pathname: P) -> Self {
let lines: Vec<String> = file_to_lines(pathname);
let plots = (0_isize..)
.zip(lines.iter())
.flat_map(move |(y, row)| {
(0_isize..).zip(row.chars()).filter_map(move |(x, c)| {
if c != '#' {
Some(Position::new(x, y))
} else {
None
}
})
})
.collect();
Self { plots }
}
fn part_1(&mut self) -> Output1 {
Steps::new(&self.plots).nth(64).unwrap()
}
fn part_2(&mut self) -> Output2 {
let steps = Steps::new(&self.plots).take(328).collect_vec();
let (x0, y0) = (65_f64, steps[65] as f64);
let (x1, y1) = (196_f64, steps[196] as f64);
let (x2, y2) = (327_f64, steps[327] as f64);
let y01 = (y1 - y0) / (x1 - x0);
let y12 = (y2 - y1) / (x2 - x1);
let y012 = (y12 - y01) / (x2 - x0);
let n = 26501365_f64;
y0 + y01 * (n - x0) + y012 * (n - x0) * (n - x1)
}
}
fn main() -> Result<()> {
Day21::main()
}
test_sample!(day_21, Day21, 0, 0);