day16 solution
parent
b6111fe337
commit
055946115a
|
@ -0,0 +1,220 @@
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
#[aoc_generator(day16)]
|
||||||
|
fn parse(input: &str) -> Vec<Vec<char>> {
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.filter_map(|line| {
|
||||||
|
if !line.is_empty() {
|
||||||
|
Some(line.chars().collect())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
enum Dir {
|
||||||
|
North,
|
||||||
|
East,
|
||||||
|
South,
|
||||||
|
West,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visited_spaces(
|
||||||
|
map: &[Vec<char>],
|
||||||
|
visited: &mut HashSet<(i64, i64, Dir)>,
|
||||||
|
start_x: i64,
|
||||||
|
start_y: i64,
|
||||||
|
start_dir: Dir,
|
||||||
|
depth: usize,
|
||||||
|
) {
|
||||||
|
if start_x < 0
|
||||||
|
|| start_y < 0
|
||||||
|
|| start_x as usize > (map.len() - 1)
|
||||||
|
|| start_y as usize > (map[0].len() - 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut x = start_x;
|
||||||
|
let mut y = start_y;
|
||||||
|
let mut dir = start_dir;
|
||||||
|
if visited.contains(&(x, y, dir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loop {
|
||||||
|
let now = (x, y, dir);
|
||||||
|
if visited.contains(&now) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
visited.insert((x, y, dir));
|
||||||
|
}
|
||||||
|
match dir {
|
||||||
|
Dir::North => match map[x as usize][y as usize] {
|
||||||
|
'/' => dir = Dir::East,
|
||||||
|
'\\' => dir = Dir::West,
|
||||||
|
'|' => {}
|
||||||
|
'-' => {
|
||||||
|
visited_spaces(map, visited, x, y, Dir::West, depth + 1);
|
||||||
|
dir = Dir::East;
|
||||||
|
}
|
||||||
|
'.' => {}
|
||||||
|
n @ _ => panic!("unknown map piece {}", n),
|
||||||
|
},
|
||||||
|
Dir::South => match map[x as usize][y as usize] {
|
||||||
|
'/' => dir = Dir::West,
|
||||||
|
'\\' => dir = Dir::East,
|
||||||
|
'|' => {}
|
||||||
|
'-' => {
|
||||||
|
visited_spaces(map, visited, x, y, Dir::West, depth + 1);
|
||||||
|
dir = Dir::East;
|
||||||
|
}
|
||||||
|
'.' => {}
|
||||||
|
n @ _ => panic!("unknown map piece {}", n),
|
||||||
|
},
|
||||||
|
Dir::East => match map[x as usize][y as usize] {
|
||||||
|
'/' => dir = Dir::North,
|
||||||
|
'\\' => dir = Dir::South,
|
||||||
|
'|' => {
|
||||||
|
visited_spaces(map, visited, x, y, Dir::North, depth + 1);
|
||||||
|
dir = Dir::South;
|
||||||
|
}
|
||||||
|
'-' => {}
|
||||||
|
'.' => {}
|
||||||
|
n @ _ => panic!("unknown map piece {}", n),
|
||||||
|
},
|
||||||
|
Dir::West => match map[x as usize][y as usize] {
|
||||||
|
'/' => dir = Dir::South,
|
||||||
|
'\\' => dir = Dir::North,
|
||||||
|
'|' => {
|
||||||
|
visited_spaces(map, visited, x, y, Dir::North, depth + 1);
|
||||||
|
dir = Dir::South;
|
||||||
|
}
|
||||||
|
'-' => {}
|
||||||
|
'.' => {}
|
||||||
|
n @ _ => panic!("unknown map piece {}", n),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
match dir {
|
||||||
|
Dir::North => {
|
||||||
|
x -= 1;
|
||||||
|
if x < 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::South => {
|
||||||
|
x += 1;
|
||||||
|
if x as usize >= map.len() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::East => {
|
||||||
|
y += 1;
|
||||||
|
if y as usize >= map[0].len() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::West => {
|
||||||
|
y -= 1;
|
||||||
|
if y < 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn energized_squares(visited: &HashSet<(i64, i64, Dir)>) -> usize {
|
||||||
|
let mut t: HashSet<(i64, i64)> = HashSet::new();
|
||||||
|
for i in visited.iter() {
|
||||||
|
t.insert((i.0, i.1));
|
||||||
|
}
|
||||||
|
t.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day16, part1)]
|
||||||
|
fn part1(input: &[Vec<char>]) -> usize {
|
||||||
|
let mut visited: HashSet<(i64, i64, Dir)> = HashSet::new();
|
||||||
|
visited_spaces(input, &mut visited, 0, 0, Dir::East, 0);
|
||||||
|
energized_squares(&visited)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day16, part2)]
|
||||||
|
fn part2(input: &[Vec<char>]) -> usize {
|
||||||
|
let mut max = 0;
|
||||||
|
let xlen = input.len() - 1;
|
||||||
|
let ylen = input[0].len() - 1;
|
||||||
|
|
||||||
|
for t in 0..=xlen {
|
||||||
|
let mut evisited: HashSet<(i64, i64, Dir)> = HashSet::new();
|
||||||
|
visited_spaces(input, &mut evisited, t as i64, 0, Dir::East, 0);
|
||||||
|
let emax = energized_squares(&evisited);
|
||||||
|
if emax > max {
|
||||||
|
max = emax;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut wvisited: HashSet<(i64, i64, Dir)> = HashSet::new();
|
||||||
|
visited_spaces(
|
||||||
|
input,
|
||||||
|
&mut wvisited,
|
||||||
|
xlen as i64,
|
||||||
|
(ylen - t) as i64,
|
||||||
|
Dir::West,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
let wmax = energized_squares(&wvisited);
|
||||||
|
if wmax > max {
|
||||||
|
max = wmax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for t in 0..=ylen {
|
||||||
|
let mut svisited: HashSet<(i64, i64, Dir)> = HashSet::new();
|
||||||
|
visited_spaces(input, &mut svisited, 0, t as i64, Dir::South, 0);
|
||||||
|
let smax = energized_squares(&svisited);
|
||||||
|
if smax > max {
|
||||||
|
max = smax;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nvisited: HashSet<(i64, i64, Dir)> = HashSet::new();
|
||||||
|
visited_spaces(
|
||||||
|
input,
|
||||||
|
&mut nvisited,
|
||||||
|
xlen as i64,
|
||||||
|
(ylen - t) as i64,
|
||||||
|
Dir::North,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
let nmax = energized_squares(&nvisited);
|
||||||
|
if nmax > max {
|
||||||
|
max = nmax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
max
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const SAMPLE_DATA: &'static str = r#".|...\....
|
||||||
|
|.-.\.....
|
||||||
|
.....|-...
|
||||||
|
........|.
|
||||||
|
..........
|
||||||
|
.........\
|
||||||
|
..../.\\..
|
||||||
|
.-.-/..|..
|
||||||
|
.|....-|.\
|
||||||
|
..//.|...."#;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_data() {
|
||||||
|
let input = parse(&SAMPLE_DATA);
|
||||||
|
assert_eq!(part1(&input), 46);
|
||||||
|
assert_eq!(part2(&input), 51);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,5 +15,6 @@ mod day12;
|
||||||
mod day13;
|
mod day13;
|
||||||
mod day14;
|
mod day14;
|
||||||
mod day15;
|
mod day15;
|
||||||
|
mod day16;
|
||||||
|
|
||||||
aoc_lib! { year = 2023 }
|
aoc_lib! { year = 2023 }
|
||||||
|
|
Loading…
Reference in New Issue