feat: added day 15 part 1 and 2
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 5s
Build and run challenges / Challenge for day (12) (push) Successful in 3s
Build and run challenges / Challenge for day (14) (push) Successful in 3s
Build and run challenges / Challenge for day (10) (push) Successful in 3s
Build and run challenges / Challenge for day (11) (push) Successful in 3s
Build and run challenges / Challenge for day (13) (push) Successful in 3s
Build and run challenges / Challenge for day (15) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 5s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (6) (push) Successful in 5s
Build and run challenges / Challenge for day (7) (push) Successful in 4s
Build and run challenges / Challenge for day (3) (push) Successful in 12s
Build and run challenges / Challenge for day (8) (push) Successful in 3s
Build and run challenges / Challenge for day (9) (push) Successful in 3s
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 5s
Build and run challenges / Challenge for day (12) (push) Successful in 3s
Build and run challenges / Challenge for day (14) (push) Successful in 3s
Build and run challenges / Challenge for day (10) (push) Successful in 3s
Build and run challenges / Challenge for day (11) (push) Successful in 3s
Build and run challenges / Challenge for day (13) (push) Successful in 3s
Build and run challenges / Challenge for day (15) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 5s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (6) (push) Successful in 5s
Build and run challenges / Challenge for day (7) (push) Successful in 4s
Build and run challenges / Challenge for day (3) (push) Successful in 12s
Build and run challenges / Challenge for day (8) (push) Successful in 3s
Build and run challenges / Challenge for day (9) (push) Successful in 3s
Signed-off-by: Louis Vallat <contact@louis-vallat.dev>
This commit is contained in:
parent
31af19e368
commit
ade16938e1
@ -11,7 +11,7 @@ jobs:
|
||||
name: Challenge for day
|
||||
strategy:
|
||||
matrix:
|
||||
day_number: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||
day_number: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||
runs-on: rust-bookworm
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
|
6
day15/Cargo.toml
Normal file
6
day15/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day15"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
180
day15/src/main.rs
Normal file
180
day15/src/main.rs
Normal file
@ -0,0 +1,180 @@
|
||||
use std::collections::HashSet;
|
||||
use std::{env, fs};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
enum Position {
|
||||
Free,
|
||||
Box,
|
||||
RightHalfBox,
|
||||
LeftHalfBox,
|
||||
Wall,
|
||||
}
|
||||
|
||||
fn read_input(path: &str) -> String {
|
||||
fs::read_to_string(path).expect("Cannot read file.")
|
||||
}
|
||||
|
||||
fn parse_input(
|
||||
input: &str,
|
||||
) -> (
|
||||
Vec<Vec<Position>>,
|
||||
Vec<Vec<Position>>,
|
||||
Vec<(i32, i32)>,
|
||||
(usize, usize),
|
||||
) {
|
||||
let mut map = Vec::new();
|
||||
let mut enlarged_map = Vec::new();
|
||||
let mut moves = Vec::new();
|
||||
let mut robot = (0, 0);
|
||||
let (raw_map, raw_moves) = input.split_once("\n\n").unwrap();
|
||||
for (row, line) in raw_map.lines().enumerate() {
|
||||
map.push(Vec::new());
|
||||
enlarged_map.push(Vec::new());
|
||||
for (col, char) in line.chars().enumerate() {
|
||||
match char {
|
||||
'#' => {
|
||||
map.last_mut().unwrap().push(Position::Wall);
|
||||
enlarged_map
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.extend(vec![Position::Wall; 2]);
|
||||
}
|
||||
'O' => {
|
||||
map.last_mut().unwrap().push(Position::Box);
|
||||
enlarged_map
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.extend(vec![Position::LeftHalfBox, Position::RightHalfBox]);
|
||||
}
|
||||
'.' | '@' => {
|
||||
map.last_mut().unwrap().push(Position::Free);
|
||||
enlarged_map
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.extend(vec![Position::Free; 2]);
|
||||
if char == '@' {
|
||||
robot = (row, col);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for line in raw_moves.lines().filter(|l| !l.is_empty()) {
|
||||
for movement in line.chars() {
|
||||
match movement {
|
||||
'^' => moves.push((-1, 0)),
|
||||
'>' => moves.push((0, 1)),
|
||||
'v' => moves.push((1, 0)),
|
||||
'<' => moves.push((0, -1)),
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moves.reverse();
|
||||
(map, enlarged_map, moves, robot)
|
||||
}
|
||||
|
||||
fn boxes_to_move(
|
||||
map: &Vec<Vec<Position>>,
|
||||
pos: &(usize, usize),
|
||||
movement: &(i32, i32),
|
||||
) -> Option<Vec<(usize, usize, Position)>> {
|
||||
let target_pos = (
|
||||
(pos.0 as i32 + movement.0) as usize,
|
||||
(pos.1 as i32 + movement.1) as usize,
|
||||
);
|
||||
match map[pos.0][pos.1] {
|
||||
Position::Free => return Some(vec![]),
|
||||
Position::Wall => return None,
|
||||
Position::Box => {
|
||||
if let Some(mut boxes) = boxes_to_move(&map, &target_pos, movement) {
|
||||
boxes.push((pos.0, pos.1, Position::Box));
|
||||
return Some(boxes);
|
||||
}
|
||||
}
|
||||
Position::LeftHalfBox | Position::RightHalfBox => {
|
||||
let other_box;
|
||||
let offset;
|
||||
if map[pos.0][pos.1] == Position::LeftHalfBox {
|
||||
other_box = Position::RightHalfBox;
|
||||
offset = 1;
|
||||
} else {
|
||||
other_box = Position::LeftHalfBox;
|
||||
offset = -1;
|
||||
}
|
||||
let target_other_half = (target_pos.0, (target_pos.1 as i32 + offset) as usize);
|
||||
if let Some(mut boxes) = boxes_to_move(&map, &target_pos, movement) {
|
||||
boxes.push((pos.0, pos.1, map[pos.0][pos.1]));
|
||||
if movement.0 != 0 {
|
||||
let other_boxes = boxes_to_move(&map, &target_other_half, movement);
|
||||
return if other_boxes.is_some() {
|
||||
boxes.append(&mut other_boxes.unwrap());
|
||||
boxes.push((pos.0, (pos.1 as i32 + offset) as usize, other_box));
|
||||
Some(boxes)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
return Some(boxes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn apply_all_moves(map: &mut Vec<Vec<Position>>, robot: &(usize, usize), moves: &Vec<(i32, i32)>) {
|
||||
let mut robot = *robot;
|
||||
for movement in moves.iter().rev() {
|
||||
let target_pos = (
|
||||
(robot.0 as i32 + movement.0) as usize,
|
||||
(robot.1 as i32 + movement.1) as usize,
|
||||
);
|
||||
if let Some(box_positions) = boxes_to_move(map, &target_pos, &movement) {
|
||||
let mut positions_moved = HashSet::new();
|
||||
for box_position in box_positions {
|
||||
if positions_moved.insert(box_position) {
|
||||
map[(box_position.0 as i32 + movement.0) as usize]
|
||||
[(box_position.1 as i32 + movement.1) as usize] = box_position.2;
|
||||
map[box_position.0][box_position.1] = Position::Free;
|
||||
}
|
||||
}
|
||||
robot = target_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_gps_score(map: &Vec<Vec<Position>>) -> usize {
|
||||
let mut sum = 0;
|
||||
for (row, line) in map.iter().enumerate() {
|
||||
for (col, position) in line.iter().enumerate() {
|
||||
if *position == Position::Box || *position == Position::LeftHalfBox {
|
||||
sum += 100 * row + col;
|
||||
}
|
||||
}
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
for arg in args.iter().skip(1) {
|
||||
let input = read_input(&arg);
|
||||
let (mut map, mut enlarged_map, moves, robot) = parse_input(&input);
|
||||
apply_all_moves(&mut map, &robot, &moves);
|
||||
apply_all_moves(&mut enlarged_map, &(robot.0, robot.1 * 2), &moves);
|
||||
println!("[{}]", &arg);
|
||||
println!("\t[Part 1] => Answer is '{}'.", compute_gps_score(&map));
|
||||
println!(
|
||||
"\t[Part 2] => Answer is '{}'.",
|
||||
compute_gps_score(&enlarged_map)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user