1
0
Fork 0

day(16): add solution

Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
Matej Focko 2023-12-16 22:16:12 +01:00
parent 57d3761793
commit fffaaf0637
Signed by: mfocko
GPG key ID: 7C47D46246790496
2 changed files with 132 additions and 0 deletions

10
samples/day16.txt Normal file
View file

@ -0,0 +1,10 @@
.|...\....
|.-.\.....
.....|-...
........|.
..........
.........\
..../.\\..
.-.-/..|..
.|....-|.\
..//.|....

122
src/bin/day16.rs Normal file
View file

@ -0,0 +1,122 @@
use std::collections::VecDeque;
use rayon::prelude::*;
use aoc_2023::*;
type Output1 = usize;
type Output2 = Output1;
type Position = Vector2D<isize>;
fn direction(d: &Position) -> i32 {
match (d.x(), d.y()) {
(1, _) => 1,
(_, 1) => 2,
(-1, _) => 4,
(_, -1) => 8,
_ => unreachable!("invalid direction"),
}
}
fn next(c: char, d: Position) -> Vec<Position> {
match c {
'|' if d.x() != 0 => vec![Vector2D::new(0, 1), Vector2D::new(0, -1)],
'-' if d.y() != 0 => vec![Vector2D::new(1, 0), Vector2D::new(-1, 0)],
'/' => vec![Vector2D::new(-d.y(), -d.x())],
'\\' => vec![Vector2D::new(d.y(), d.x())],
_ => vec![d],
}
}
// fn draw_energized(map: &[Vec<i32>]) {
// let mut formatted = String::new();
// for row in map {
// for &c in row {
// formatted += if c != 0 { "#" } else { "." };
// }
// formatted += "\n";
// }
// debug!("Energized:\n{}", formatted);
// }
struct Day16 {
map: Vec<Vec<char>>,
}
impl Day16 {
fn solve(&self, start_pos: Position, start_dir: Position) -> usize {
let mut visited = vec![vec![0; self.map[0].len()]; self.map.len()];
let mut q: VecDeque<(Position, Position)> = VecDeque::new();
q.push_back((start_pos, start_dir));
visited[start_pos] |= direction(&start_dir);
while let Some((p, d)) = q.pop_front() {
for dp in next(self.map[p], d) {
if !in_range(&self.map, &(p + dp)) || visited[p + dp] & direction(&dp) != 0 {
continue;
}
visited[p + dp] |= direction(&dp);
q.push_back((p + dp, dp));
}
}
// draw_energized(&visited);
visited
.iter()
.map(|row| row.iter().filter(|&&c| c != 0).count())
.sum()
}
}
impl Solution<Output1, Output2> for Day16 {
fn new<P: AsRef<Path>>(pathname: P) -> Self {
Self {
map: file_to_string(pathname)
.lines()
.map(|l| l.chars().collect())
.collect(),
}
}
fn part_1(&mut self) -> Output1 {
self.solve(Vector2D::new(0, 0), Vector2D::new(1, 0))
}
fn part_2(&mut self) -> Output2 {
(0..self.map.len())
.into_par_iter()
.flat_map(|y| {
vec![
(Vector2D::new(0, y as isize), Vector2D::new(1, 0)),
(
Vector2D::new(self.map[y].len() as isize - 1, y as isize),
Vector2D::new(-1, 0),
),
]
})
.chain((0..self.map[0].len()).into_par_iter().flat_map(|x| {
vec![
(Vector2D::new(x as isize, 0), Vector2D::new(0, 1)),
(
Vector2D::new(x as isize, self.map.len() as isize - 1),
Vector2D::new(0, -1),
),
]
}))
.map(|(start_pos, start_dir)| self.solve(start_pos, start_dir))
.max()
.unwrap()
}
}
fn main() -> Result<()> {
Day16::main()
}
test_sample!(day_16, Day16, 46, 51);