day 15 part 2
This commit is contained in:
138
src/day15.rs
138
src/day15.rs
@@ -1,6 +1,8 @@
|
||||
use std::fs::read_to_string;
|
||||
use std::{collections::HashSet, fs::read_to_string};
|
||||
|
||||
use crate::utils::grid::Grid;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::utils::grid::{Coord, Grid};
|
||||
|
||||
pub fn day_main() {
|
||||
let input = read_to_string("input/day15.txt").unwrap();
|
||||
@@ -44,8 +46,111 @@ fn part1(input: &str) -> RiddleResult {
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn part2(_input: &str) -> RiddleResult {
|
||||
0
|
||||
fn part2(input: &str) -> RiddleResult {
|
||||
let (grid, movements) = input.split_once("\n\n").unwrap();
|
||||
let grid = grid
|
||||
.lines()
|
||||
.map(|line| {
|
||||
{
|
||||
line.chars().flat_map(|c| {
|
||||
match c {
|
||||
'.' => "..",
|
||||
'@' => "@.",
|
||||
'#' => "##",
|
||||
'O' => "[]",
|
||||
_ => panic!(),
|
||||
}
|
||||
.chars()
|
||||
})
|
||||
}
|
||||
.join("")
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
let mut grid = Grid::parse(grid.as_str());
|
||||
|
||||
let mut robot = grid.entries().find(|(_r, c)| **c == '@').unwrap().0;
|
||||
let directions = |d| match d {
|
||||
'^' => (0, -1),
|
||||
'v' => (0, 1),
|
||||
'<' => (-1, 0),
|
||||
'>' => (1, 0),
|
||||
_ => panic!(),
|
||||
};
|
||||
for m in movements.chars().filter(|c| *c != '\n') {
|
||||
let dir = directions(m);
|
||||
if let Some(tiles_to_move) = movable(robot, dir, &grid, false) {
|
||||
let old = tiles_to_move
|
||||
.iter()
|
||||
.map(|tile| (*tile, grid[*tile]))
|
||||
.collect_vec();
|
||||
tiles_to_move.iter().for_each(|tile| grid[*tile] = '.');
|
||||
old.into_iter()
|
||||
.for_each(|(tile, c)| grid[(tile.0 + dir.0, tile.1 + dir.1)] = c);
|
||||
robot = (robot.0 + dir.0, robot.1 + dir.1);
|
||||
}
|
||||
}
|
||||
grid.entries()
|
||||
.filter(|(_, c)| **c == '[')
|
||||
.map(|((x, y), _)| y * 100 + x)
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn movable(
|
||||
from: (i64, i64),
|
||||
dir: (i64, i64),
|
||||
grid: &Grid<char>,
|
||||
ignore_other_half: bool,
|
||||
) -> Option<HashSet<Coord>> {
|
||||
match grid[from] {
|
||||
'.' => Some(HashSet::new()),
|
||||
'@' => {
|
||||
let next = movable((from.0 + dir.0, from.1 + dir.1), dir, grid, false);
|
||||
next.map(|mut v| {
|
||||
v.insert(from);
|
||||
v
|
||||
})
|
||||
}
|
||||
'[' => {
|
||||
if dir.0 != 0 {
|
||||
// sideway movement is "regular"
|
||||
let next = movable((from.0 + dir.0, from.1 + dir.1), dir, grid, false);
|
||||
next.map(|mut v| {
|
||||
v.insert(from);
|
||||
v
|
||||
})
|
||||
} else {
|
||||
// up/down always means the other part of the crate has to move in parallel
|
||||
let mut next1 = movable((from.0 + dir.0, from.1 + dir.1), dir, grid, false)?;
|
||||
if !ignore_other_half {
|
||||
let next2 = movable((from.0 + 1, from.1), dir, grid, true)?;
|
||||
next1.extend(next2);
|
||||
}
|
||||
next1.insert(from);
|
||||
Some(next1)
|
||||
}
|
||||
}
|
||||
']' => {
|
||||
if dir.0 != 0 {
|
||||
// sideway movement is "regular"
|
||||
let next = movable((from.0 + dir.0, from.1 + dir.1), dir, grid, false);
|
||||
next.map(|mut v| {
|
||||
v.insert(from);
|
||||
v
|
||||
})
|
||||
} else {
|
||||
// up/down always means the other part of the crate has to move in parallel
|
||||
let mut next1 = movable((from.0 + dir.0, from.1 + dir.1), dir, grid, false)?;
|
||||
if !ignore_other_half {
|
||||
let next2 = movable((from.0 - 1, from.1), dir, grid, true)?;
|
||||
next1.extend(next2);
|
||||
}
|
||||
next1.insert(from);
|
||||
Some(next1)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -63,6 +168,29 @@ mod test {
|
||||
|
||||
<^^>>>vv<v>>v<<";
|
||||
|
||||
const TEST_LARGE: &str = r"##########
|
||||
#..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^<<^
|
||||
";
|
||||
|
||||
#[test]
|
||||
fn test1() {
|
||||
assert_eq!(part1(TEST_INPUT), 2028);
|
||||
@@ -70,6 +198,6 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test2() {
|
||||
assert_eq!(part2(TEST_INPUT), 0);
|
||||
assert_eq!(part2(TEST_LARGE), 9021);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,15 @@ impl Grid<char> {
|
||||
content,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(&self) {
|
||||
for line in &self.content.iter().chunks(self.content_width as usize) {
|
||||
for c in line.into_iter() {
|
||||
print!("{c}");
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<Coord> for Grid<T> {
|
||||
|
||||
Reference in New Issue
Block a user