day(16): add solution
Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
parent
57d3761793
commit
fffaaf0637
2 changed files with 132 additions and 0 deletions
10
samples/day16.txt
Normal file
10
samples/day16.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
.|...\....
|
||||
|.-.\.....
|
||||
.....|-...
|
||||
........|.
|
||||
..........
|
||||
.........\
|
||||
..../.\\..
|
||||
.-.-/..|..
|
||||
.|....-|.\
|
||||
..//.|....
|
122
src/bin/day16.rs
Normal file
122
src/bin/day16.rs
Normal 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);
|
Loading…
Reference in a new issue