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 day14;
|
||||
mod day15;
|
||||
mod day16;
|
||||
|
||||
aoc_lib! { year = 2023 }
|
||||
|
|
Loading…
Reference in New Issue