generated from janezicmatej/aoc-template
solution: day 15
This commit is contained in:
parent
000001801f
commit
0000019062
|
@ -0,0 +1,21 @@
|
|||
##########
|
||||
#..O..O.O#
|
||||
#......O.#
|
||||
#.OO..O.O#
|
||||
#..O@..O.#
|
||||
#O#..O...#
|
||||
#O..O..O.#
|
||||
#.OO.O.OO#
|
||||
#....O...#
|
||||
##########
|
||||
|
||||
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
|
||||
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
|
||||
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
|
||||
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
|
||||
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
|
||||
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
|
||||
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
|
||||
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
|
||||
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
|
||||
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
|
|
@ -0,0 +1,209 @@
|
|||
use hashbrown::HashSet;
|
||||
use itertools::Itertools;
|
||||
|
||||
struct ParsedInput {
|
||||
map: Vec<Vec<char>>,
|
||||
dirs: Vec<(isize, isize)>,
|
||||
start: (usize, usize),
|
||||
}
|
||||
|
||||
fn dir_mapper(c: char) -> (isize, isize) {
|
||||
match c {
|
||||
'>' => (0, 1),
|
||||
'<' => (0, -1),
|
||||
'v' => (1, 0),
|
||||
'^' => (-1, 0),
|
||||
_ => unreachable!("found dir {c}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_input(input: &str, extend: bool) -> ParsedInput {
|
||||
let (umap, uins) = input.split_once("\n\n").unwrap();
|
||||
|
||||
let mut map = Vec::new();
|
||||
|
||||
for line in umap.lines() {
|
||||
let mut row: Vec<char> = line.chars().collect();
|
||||
if extend {
|
||||
row = line
|
||||
.chars()
|
||||
.flat_map(|x| {
|
||||
let y = match x {
|
||||
'#' => "##",
|
||||
'O' => "[]",
|
||||
'.' => "..",
|
||||
'@' => "@.",
|
||||
_ => unreachable!("found {x}"),
|
||||
};
|
||||
y.chars()
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
map.push(row);
|
||||
}
|
||||
|
||||
let dirs = uins
|
||||
.lines()
|
||||
.flat_map(|x| x.chars().map(dir_mapper))
|
||||
.collect_vec();
|
||||
|
||||
let (si, sj, _) = map
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, x)| x.iter().copied().enumerate().map(move |(j, y)| (i, j, y)))
|
||||
.find(|x| x.2 == '@')
|
||||
.unwrap();
|
||||
|
||||
ParsedInput {
|
||||
map,
|
||||
dirs,
|
||||
start: (si, sj),
|
||||
}
|
||||
}
|
||||
|
||||
fn boxes_gps(map: &[Vec<char>]) -> usize {
|
||||
map.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, x)| {
|
||||
x.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, y)| ['O', '['].contains(y))
|
||||
.map(move |(j, _)| 100 * i + j)
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
pub fn part_one(input: &str) -> Option<usize> {
|
||||
let ParsedInput {
|
||||
mut map,
|
||||
dirs,
|
||||
start: (mut si, mut sj),
|
||||
} = parse_input(input, false);
|
||||
|
||||
for (di, dj) in dirs.iter().copied() {
|
||||
let mut box_count = 0;
|
||||
|
||||
loop {
|
||||
if map[si][sj] == 'O' {
|
||||
box_count += 1;
|
||||
map[si][sj] = '.';
|
||||
}
|
||||
|
||||
map[si][sj] = '.';
|
||||
|
||||
let ni = si.wrapping_add(di as usize);
|
||||
let nj = sj.wrapping_add(dj as usize);
|
||||
|
||||
if map[ni][nj] == '#' {
|
||||
break;
|
||||
}
|
||||
|
||||
(si, sj) = (ni, nj);
|
||||
|
||||
if map[si][sj] == '.' {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let (di, dj) = (-di, -dj);
|
||||
|
||||
for _ in 0..box_count {
|
||||
map[si][sj] = 'O';
|
||||
si = si.wrapping_add(di as usize);
|
||||
sj = sj.wrapping_add(dj as usize);
|
||||
}
|
||||
|
||||
map[si][sj] = '@';
|
||||
}
|
||||
|
||||
boxes_gps(&map).into()
|
||||
}
|
||||
|
||||
fn can_move_and_mark(
|
||||
acc: &mut HashSet<(usize, usize, usize)>,
|
||||
mark: usize,
|
||||
map: &[Vec<char>],
|
||||
loc: (usize, usize),
|
||||
dir: (isize, isize),
|
||||
) -> bool {
|
||||
let (li, mut lj) = loc;
|
||||
|
||||
match map[li][lj] {
|
||||
'.' => return true,
|
||||
'#' => return false,
|
||||
']' => lj -= 1,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let mut cmm = |l, dir| can_move_and_mark(acc, mark + 1, map, l, dir);
|
||||
|
||||
let can_move = match dir {
|
||||
(0, -1) => cmm((li, lj - 1), dir),
|
||||
(0, 1) => cmm((li, lj + 2), dir),
|
||||
(-1, 0) => cmm((li - 1, lj), dir) && cmm((li - 1, lj + 1), dir),
|
||||
(1, 0) => cmm((li + 1, lj), dir) && cmm((li + 1, lj + 1), dir),
|
||||
x => unreachable!("found dir {x:?}"),
|
||||
};
|
||||
|
||||
if can_move {
|
||||
acc.insert((li, lj, mark));
|
||||
}
|
||||
|
||||
can_move
|
||||
}
|
||||
|
||||
pub fn part_two(input: &str) -> Option<usize> {
|
||||
let ParsedInput {
|
||||
mut map,
|
||||
dirs,
|
||||
start: (mut si, mut sj),
|
||||
} = parse_input(input, true);
|
||||
|
||||
let mut marker = HashSet::new();
|
||||
let mut sorter = Vec::new();
|
||||
|
||||
for (di, dj) in dirs.iter().copied() {
|
||||
marker.clear();
|
||||
sorter.clear();
|
||||
|
||||
let ni = si.wrapping_add(di as usize);
|
||||
let nj = sj.wrapping_add(dj as usize);
|
||||
|
||||
if can_move_and_mark(&mut marker, 0, &map, (ni, nj), (di, dj)) {
|
||||
sorter.extend(marker.drain());
|
||||
sorter.sort_by_key(|x| -(x.2 as isize));
|
||||
|
||||
for (mi, mj, _) in sorter.iter().copied() {
|
||||
let nmi = mi.wrapping_add(di as usize);
|
||||
let nmj = mj.wrapping_add(dj as usize);
|
||||
|
||||
map[mi][mj] = '.';
|
||||
map[mi][mj + 1] = '.';
|
||||
map[nmi][nmj] = '[';
|
||||
map[nmi][nmj + 1] = ']';
|
||||
}
|
||||
|
||||
map[si][sj] = '.';
|
||||
(si, sj) = (ni, nj);
|
||||
map[si][sj] = '@';
|
||||
}
|
||||
}
|
||||
|
||||
boxes_gps(&map).into()
|
||||
}
|
||||
|
||||
aoc::solution!(15);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_part_one() {
|
||||
assert_eq!(part_one(&aoc::template::read_file("examples", 15)), Some(10092));
|
||||
}
|
||||
#[test]
|
||||
fn test_part_two() {
|
||||
assert_eq!(part_two(&aoc::template::read_file("examples", 15)), Some(9021));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue