Add day15 part2
This commit is contained in:
parent
b813526dfe
commit
35c3e99fbc
@ -2,11 +2,13 @@ use std::{collections::VecDeque, fmt::Display};
|
|||||||
|
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
||||||
enum Tile {
|
enum Tile {
|
||||||
Wall,
|
Wall,
|
||||||
Robot,
|
Robot,
|
||||||
Box,
|
Box,
|
||||||
|
BoxL,
|
||||||
|
BoxR,
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
use Tile::*;
|
use Tile::*;
|
||||||
@ -17,6 +19,8 @@ impl Display for Tile {
|
|||||||
Wall => write!(f, "#"),
|
Wall => write!(f, "#"),
|
||||||
Robot => write!(f, "@"),
|
Robot => write!(f, "@"),
|
||||||
Box => write!(f, "O"),
|
Box => write!(f, "O"),
|
||||||
|
BoxL => write!(f, "["),
|
||||||
|
BoxR => write!(f, "]"),
|
||||||
Empty => write!(f, "."),
|
Empty => write!(f, "."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,6 +66,27 @@ impl Display for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn widen(&mut self) {
|
||||||
|
self.map = self
|
||||||
|
.map
|
||||||
|
.iter()
|
||||||
|
.map(|l| {
|
||||||
|
l.iter()
|
||||||
|
.flat_map(|t| match t {
|
||||||
|
Empty => [Empty, Empty],
|
||||||
|
Wall => [Wall, Wall],
|
||||||
|
Box => [BoxL, BoxR],
|
||||||
|
Robot => [Robot, Empty],
|
||||||
|
e => [*e, *e],
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
self.robot_pos *= IVec2::new(1, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse(input: &str) -> State {
|
fn parse(input: &str) -> State {
|
||||||
let (map, directions) = input.split_once("\n\n").unwrap();
|
let (map, directions) = input.split_once("\n\n").unwrap();
|
||||||
let mut robot_pos = IVec2::new(0, 0);
|
let mut robot_pos = IVec2::new(0, 0);
|
||||||
@ -105,6 +130,31 @@ fn get_tile<'a>(map: &'a mut [Vec<Tile>], idx: &IVec2) -> &'a mut Tile {
|
|||||||
&mut map[idx.x as usize][idx.y as usize]
|
&mut map[idx.x as usize][idx.y as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn can_be_moved(state: &State, pos: &IVec2, direction: &IVec2, to_move: &mut Vec<IVec2>) -> bool {
|
||||||
|
let tile_in_front = state.map[(pos + direction).x as usize][(pos + direction).y as usize];
|
||||||
|
if tile_in_front == Wall {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if tile_in_front == Empty {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let to_check_dir = match tile_in_front {
|
||||||
|
BoxL => Right.as_vec(),
|
||||||
|
BoxR => Left.as_vec(),
|
||||||
|
_ => IVec2::new(0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
if direction == &Up.as_vec() || direction == &Down.as_vec() {
|
||||||
|
to_move.push(pos + direction);
|
||||||
|
to_move.push(pos + direction + to_check_dir);
|
||||||
|
return can_be_moved(state, &(pos + direction), direction, to_move)
|
||||||
|
&& can_be_moved(state, &(pos + direction + to_check_dir), direction, to_move);
|
||||||
|
}
|
||||||
|
to_move.push(pos + direction);
|
||||||
|
can_be_moved(state, &(pos + direction), direction, to_move)
|
||||||
|
}
|
||||||
|
|
||||||
fn do_move(state: &mut State) {
|
fn do_move(state: &mut State) {
|
||||||
let dir = state.directions.pop_front().unwrap().as_vec();
|
let dir = state.directions.pop_front().unwrap().as_vec();
|
||||||
let pos_in_front = state.robot_pos + dir;
|
let pos_in_front = state.robot_pos + dir;
|
||||||
@ -120,42 +170,50 @@ fn do_move(state: &mut State) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut curr = pos_in_front;
|
let mut to_move = Vec::new();
|
||||||
while get_tile(&mut state.map, &curr) != &Wall && get_tile(&mut state.map, &curr) != &Empty {
|
if can_be_moved(state, &state.robot_pos, &dir, &mut to_move) {
|
||||||
curr += dir;
|
let mut new_map = state.map.clone();
|
||||||
|
for pos in &to_move {
|
||||||
|
*get_tile(&mut new_map, pos) = Empty;
|
||||||
}
|
}
|
||||||
if get_tile(&mut state.map, &curr) == &Wall {
|
|
||||||
return;
|
for pos in &to_move {
|
||||||
|
*get_tile(&mut new_map, &(pos + dir)) = *get_tile(&mut state.map, pos);
|
||||||
}
|
}
|
||||||
*get_tile(&mut state.map, &curr) = Box;
|
state.map = new_map;
|
||||||
*get_tile(&mut state.map, &pos_in_front) = Robot;
|
*get_tile(&mut state.map, &pos_in_front) = Robot;
|
||||||
*get_tile(&mut state.map, &state.robot_pos) = Empty;
|
*get_tile(&mut state.map, &state.robot_pos) = Empty;
|
||||||
state.robot_pos = pos_in_front;
|
state.robot_pos = pos_in_front;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(state: &mut State) -> usize {
|
fn get_gps_sum(state: &State) -> usize {
|
||||||
while !state.directions.is_empty() {
|
|
||||||
do_move(state);
|
|
||||||
}
|
|
||||||
state
|
state
|
||||||
.map
|
.map
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.flat_map(|(l_idx, l)| {
|
.flat_map(|(l_idx, l)| {
|
||||||
l.iter().enumerate().map(
|
l.iter().enumerate().map(move |(t_idx, t)| {
|
||||||
move |(t_idx, t)| {
|
if t == &Box || t == &BoxL {
|
||||||
if t == &Box {
|
|
||||||
100 * l_idx + t_idx
|
100 * l_idx + t_idx
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn part12(state: &mut State) -> usize {
|
||||||
|
while !state.directions.is_empty() {
|
||||||
|
do_move(state);
|
||||||
|
}
|
||||||
|
get_gps_sum(state)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut input = parse(include_str!("../input.txt"));
|
let mut input = parse(include_str!("../input.txt"));
|
||||||
println!("{}", part1(&mut input));
|
println!("{}", part12(&mut input.clone()));
|
||||||
|
input.widen();
|
||||||
|
println!("{}", part12(&mut input));
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user