Skip to content

Commit

Permalink
Day 24: Blizzard Basin
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 24, 2022
1 parent 7ec2081 commit f8a698a
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 2 deletions.
6 changes: 5 additions & 1 deletion rs/benches/criterion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ extern crate build_const;

use aoc2022::{
day1, day10, day11, day12, day13, day13_fast, day14, day15, day16, day17, day18, day19, day2,
day20, day21, day22, day23, day3, day4, day5, day6, day7, day8, day9,
day20, day21, day22, day23, day24, day3, day4, day5, day6, day7, day8, day9,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use gag::Gag;
Expand Down Expand Up @@ -115,6 +115,10 @@ fn aoc2022_bench(c: &mut Criterion) {
g.bench_function("part 1", |b| b.iter(|| day23::part1(black_box(DAY23))));
g.bench_function("part 2", |b| b.iter(|| day23::part2(black_box(DAY23))));
g.finish();
let mut g = c.benchmark_group("day 24");
g.bench_function("part 1", |b| b.iter(|| day24::part1(black_box(DAY24))));
g.bench_function("part 2", |b| b.iter(|| day24::part2(black_box(DAY24))));
g.finish();
}

criterion_group!(aoc2022, aoc2022_bench);
Expand Down
111 changes: 111 additions & 0 deletions rs/src/day24.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use std::cmp::Reverse;
use std::collections::{BinaryHeap, HashSet};
use std::ops::Range;

fn add_mod_range(a: usize, b: usize, range: Range<usize>) -> usize {
(a - range.start + b) % range.len() + range.start
}

fn sub_mod_range(a: usize, b: usize, range: Range<usize>) -> usize {
(a - range.start + range.len() - b % range.len()) % range.len() + range.start
}

fn search(
lines: &[&[u8]],
start: (usize, usize),
end: (usize, usize),
time: usize,
) -> Option<usize> {
let mut seen: HashSet<_> = [(start, time)].into();
let mut queue: BinaryHeap<_> = [(Reverse(0), (start, time))].into();
while let Some((_, (pos @ (x, y), time))) = queue.pop() {
if pos == end {
return Some(time);
}
for (dx, dy) in [(-1, 0), (0, -1), (0, 0), (0, 1), (1, 0)] {
let Some(x) = x.checked_add_signed(dx) else { continue };
let Some(y) = y.checked_add_signed(dy) else { continue };
if y >= lines.len() || x == 0 {
continue;
}
let line = lines[y];
if x >= line.len() - 1 {
continue;
}
if y == 0 || y == lines.len() - 1 {
if lines[y][x] != b'.' {
continue;
}
} else if line[add_mod_range(x, time + 1, 1..line.len() - 1)] == b'<'
|| line[sub_mod_range(x, time + 1, 1..line.len() - 1)] == b'>'
|| lines[add_mod_range(y, time + 1, 1..lines.len() - 1)][x] == b'^'
|| lines[sub_mod_range(y, time + 1, 1..lines.len() - 1)][x] == b'v'
{
continue;
}
if seen.insert(((x, y), time + 1)) {
queue.push((
Reverse(time + x.abs_diff(end.0) + y.abs_diff(end.1)),
((x, y), time + 1),
));
}
}
}
None
}

pub fn part1<'a, I, S>(lines: I) -> Option<usize>
where
I: IntoIterator<Item = &'a S>,
S: AsRef<str> + 'a,
{
let lines = lines
.into_iter()
.map(|line| line.as_ref().as_bytes())
.collect::<Vec<_>>();
search(
&lines,
(1, 0),
(lines.last()?.len() - 2, lines.len() - 1),
0,
)
}

pub fn part2<'a, I, S>(lines: I) -> Option<usize>
where
I: IntoIterator<Item = &'a S>,
S: AsRef<str> + 'a,
{
let lines = lines
.into_iter()
.map(|line| line.as_ref().as_bytes())
.collect::<Vec<_>>();
let start = (1, 0);
let end = (lines.last()?.len() - 2, lines.len() - 1);
search(
&lines,
start,
end,
search(&lines, end, start, search(&lines, start, end, 0)?)?,
)
}

#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;

static EXAMPLE: &[&str] = &[
"#.######", "#>>.<^<#", "#.<..<<#", "#>v.><>#", "#<^v^^>#", "######.#",
];

#[test]
fn part1_examples() {
assert_eq!(Some(18), part1(EXAMPLE));
}

#[test]
fn part2_examples() {
assert_eq!(Some(54), part2(EXAMPLE));
}
}
1 change: 1 addition & 0 deletions rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod day20;
pub mod day21;
pub mod day22;
pub mod day23;
pub mod day24;
pub mod day3;
pub mod day4;
pub mod day5;
Expand Down
9 changes: 8 additions & 1 deletion rs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ extern crate build_const;

use aoc2022::{
day1, day10, day11, day12, day13, day13_fast, day14, day15, day16, day17, day18, day19, day2,
day20, day21, day22, day23, day3, day4, day5, day6, day7, day8, day9,
day20, day21, day22, day23, day24, day3, day4, day5, day6, day7, day8, day9,
};
use std::collections::HashSet;
use std::env;
Expand Down Expand Up @@ -184,5 +184,12 @@ fn main() -> io::Result<()> {
println!();
}

if args.is_empty() || args.contains("24") {
println!("Day 24");
println!("{:?}", day24::part1(DAY24).expect("error"));
println!("{:?}", day24::part2(DAY24).expect("error"));
println!();
}

Ok(())
}

0 comments on commit f8a698a

Please sign in to comment.