2024-12-06 06:46:04 +00:00
|
|
|
type Input = ((usize, usize), Vec<Vec<u8>>);
|
|
|
|
|
2024-12-06 14:46:53 +00:00
|
|
|
use std::collections::HashSet;
|
|
|
|
|
2024-12-06 06:46:04 +00:00
|
|
|
use aoc_runner_derive::{aoc, aoc_generator};
|
|
|
|
#[aoc_generator(day6)]
|
|
|
|
fn parse(input: &str) -> Input {
|
|
|
|
let lines = input.split("\n");
|
|
|
|
let mut pos = (0, 0);
|
|
|
|
let map = lines
|
|
|
|
.enumerate()
|
|
|
|
.map(|(y, line)| {
|
|
|
|
line.chars()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(x, c)| match c {
|
|
|
|
'.' => 0,
|
|
|
|
'#' => 1,
|
|
|
|
'^' => {
|
|
|
|
pos = (x, y);
|
|
|
|
0
|
|
|
|
}
|
|
|
|
_ => todo!(),
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
(pos, map)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day6, part1)]
|
|
|
|
fn part1(input: &Input) -> u64 {
|
|
|
|
let h = input.1.len();
|
|
|
|
let w = input.1[0].len();
|
|
|
|
let mut map = input.1.clone();
|
|
|
|
let mut pos = input.0;
|
|
|
|
let mut dir = (0, -1);
|
|
|
|
let mut count = 0;
|
|
|
|
loop {
|
|
|
|
if map[pos.1][pos.0] == 0 {
|
|
|
|
map[pos.1][pos.0] = 2;
|
|
|
|
count += 1;
|
|
|
|
};
|
|
|
|
if pos.0 as isize + dir.0 < 0
|
|
|
|
|| pos.0 as isize + dir.0 >= w as isize
|
|
|
|
|| pos.1 as isize + dir.1 < 0
|
|
|
|
|| pos.1 as isize + dir.1 >= h as isize
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while map[(pos.1 as isize + dir.1) as usize][(pos.0 as isize + dir.0) as usize] == 1 {
|
|
|
|
if dir.0 == 1 {
|
|
|
|
dir = (0, 1);
|
|
|
|
} else if dir.0 == -1 {
|
|
|
|
dir = (0, -1);
|
|
|
|
} else if dir.1 == 1 {
|
|
|
|
dir = (-1, 0);
|
|
|
|
} else if dir.1 == -1 {
|
|
|
|
dir = (1, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = (
|
|
|
|
(pos.0 as isize + dir.0) as usize,
|
|
|
|
(pos.1 as isize + dir.1) as usize,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
count
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day6, part2)]
|
|
|
|
fn part2(input: &Input) -> u64 {
|
|
|
|
let initial = input.0;
|
|
|
|
let h = input.1.len();
|
|
|
|
let w = input.1[0].len();
|
|
|
|
let mut map = input.1.clone();
|
|
|
|
let mut pos = input.0;
|
|
|
|
let mut dir = (0, -1);
|
|
|
|
let mut loops = vec![];
|
|
|
|
loop {
|
|
|
|
if pos.0 as isize + dir.0 < 0
|
|
|
|
|| pos.0 as isize + dir.0 >= w as isize
|
|
|
|
|| pos.1 as isize + dir.1 < 0
|
|
|
|
|| pos.1 as isize + dir.1 >= h as isize
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while map[(pos.1 as isize + dir.1) as usize][(pos.0 as isize + dir.0) as usize] == 1 {
|
|
|
|
if dir.0 == 1 {
|
|
|
|
dir = (0, 1);
|
|
|
|
} else if dir.0 == -1 {
|
|
|
|
dir = (0, -1);
|
|
|
|
} else if dir.1 == 1 {
|
|
|
|
dir = (-1, 0);
|
|
|
|
} else if dir.1 == -1 {
|
|
|
|
dir = (1, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let next_pos = (
|
|
|
|
(pos.0 as isize + dir.0) as usize,
|
|
|
|
(pos.1 as isize + dir.1) as usize,
|
|
|
|
);
|
|
|
|
if map[next_pos.1][next_pos.0] != 1 {
|
|
|
|
map[next_pos.1][next_pos.0] = 1;
|
2024-12-06 14:46:53 +00:00
|
|
|
if check_loop(pos, dir, &map) {
|
2024-12-06 06:46:04 +00:00
|
|
|
// count += 1;
|
|
|
|
if !(loops.contains(&next_pos)) && next_pos != initial {
|
|
|
|
loops.push(next_pos);
|
|
|
|
}
|
|
|
|
// println!("{} {}", nexts_pos.0 + 1, next_pos.1 + 1);
|
|
|
|
}
|
|
|
|
map[next_pos.1][next_pos.0] = 0;
|
|
|
|
}
|
|
|
|
pos = next_pos;
|
|
|
|
}
|
|
|
|
loops.len() as u64
|
|
|
|
}
|
|
|
|
|
2024-12-06 14:46:53 +00:00
|
|
|
static mut VISITED: [[[bool; 4]; 130]; 130] = [[[false; 4]; 130]; 130];
|
|
|
|
static mut VISITED_VEC: Vec<(usize, usize, usize)> = vec![];
|
2024-12-06 06:46:04 +00:00
|
|
|
|
2024-12-06 14:46:53 +00:00
|
|
|
fn check_loop(pos: (usize, usize), dir: (isize, isize), map: &[Vec<u8>]) -> bool {
|
2024-12-06 06:46:04 +00:00
|
|
|
let h = map.len();
|
|
|
|
let w = map[0].len();
|
|
|
|
|
2024-12-06 14:46:53 +00:00
|
|
|
unsafe {
|
|
|
|
VISITED_VEC.clear();
|
|
|
|
VISITED_VEC.reserve(w * h * 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
// let mut visited = [[[false; 4]; 130]; 130];
|
|
|
|
// let mut visited = HashSet::with_capacity(h * w * 4);
|
|
|
|
// let mut visited = 0;
|
|
|
|
|
2024-12-06 06:46:04 +00:00
|
|
|
let mut dir = dir;
|
|
|
|
let mut pos = pos;
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if pos.0 as isize + dir.0 < 0
|
|
|
|
|| pos.0 as isize + dir.0 >= w as isize
|
|
|
|
|| pos.1 as isize + dir.1 < 0
|
|
|
|
|| pos.1 as isize + dir.1 >= h as isize
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
let mut turns = 0;
|
|
|
|
while map[(pos.1 as isize + dir.1) as usize][(pos.0 as isize + dir.0) as usize] == 1 {
|
|
|
|
if dir.0 == 1 {
|
|
|
|
dir = (0, 1);
|
|
|
|
} else if dir.0 == -1 {
|
|
|
|
dir = (0, -1);
|
|
|
|
} else if dir.1 == 1 {
|
|
|
|
dir = (-1, 0);
|
|
|
|
} else if dir.1 == -1 {
|
|
|
|
dir = (1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
turns += 1;
|
|
|
|
}
|
2024-12-06 14:46:53 +00:00
|
|
|
if turns == 2 {
|
|
|
|
break;
|
|
|
|
}
|
2024-12-06 06:46:04 +00:00
|
|
|
pos = (
|
|
|
|
(pos.0 as isize + dir.0) as usize,
|
|
|
|
(pos.1 as isize + dir.1) as usize,
|
|
|
|
);
|
2024-12-06 14:46:53 +00:00
|
|
|
let dirnum = ((dir.1 + 1) >> 2) as usize + (dir.0 + 1) as usize;
|
|
|
|
unsafe {
|
|
|
|
if VISITED[pos.1][pos.0][dirnum] {
|
|
|
|
clear_visited();
|
|
|
|
return true;
|
|
|
|
} else if turns > 0 {
|
|
|
|
VISITED[pos.1][pos.0][dirnum] = true;
|
|
|
|
VISITED_VEC.push((pos.0, pos.1, dirnum));
|
|
|
|
}
|
2024-12-06 06:46:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-06 14:46:53 +00:00
|
|
|
unsafe {
|
|
|
|
clear_visited();
|
|
|
|
}
|
|
|
|
|
2024-12-06 06:46:04 +00:00
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2024-12-06 14:46:53 +00:00
|
|
|
unsafe fn clear_visited() {
|
|
|
|
VISITED_VEC
|
|
|
|
.iter()
|
|
|
|
.for_each(|(a, b, c)| VISITED[*b][*a][*c] = false);
|
|
|
|
}
|
2024-12-06 06:46:04 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn part1_example() {
|
|
|
|
assert_eq!(part1(&parse("....#.....\n.........#\n..........\n..#.......\n.......#..\n..........\n.#..^.....\n........#.\n#.........\n......#...")), 41);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn part2_example() {
|
|
|
|
assert_eq!(part2(&parse("....#.....\n.........#\n..........\n..#.......\n.......#..\n..........\n.#..^.....\n........#.\n#.........\n......#...")), 6);
|
|
|
|
}
|
|
|
|
}
|