Files
advent-of-code-2024-rust/src/bin/15.rs
T

129 lines
3.5 KiB
Rust
Raw Normal View History

2024-12-16 18:08:52 +00:00
use itertools::Itertools;
advent_of_code::solution!(15);
#[derive(Debug)]
#[derive(PartialEq)]
enum TileObject {
Empty,
Wall,
Robot,
Box
}
fn get_tile_object(c: char) -> TileObject {
match c {
'.' => TileObject::Empty,
'#' => TileObject::Wall,
'@' => TileObject::Robot,
'O' => TileObject::Box,
_ => panic!()
}
}
fn get_direction(c: char) -> (isize, isize) {
match c {
'^' => (-1, 0),
'v' => (1, 0),
'<' => (0, -1),
'>' => (0, 1),
_ => panic!()
}
}
pub fn part_one(input: &str) -> Option<u32> {
let mut i = input.lines();
let mut grid = i.by_ref().take_while(|l| !l.is_empty()).map(|l| l.chars().map(|c| get_tile_object(c)).collect_vec()).collect_vec();
let moves = i.by_ref().flat_map(|l| {
l.chars().map(|c| get_direction(c)).collect_vec()
});
let mut robot_pos = grid.iter().enumerate().find_map(|(row_idx, row)| {
row.iter().enumerate().find_map(|(col_idx, t)| if *t == TileObject::Robot { Some((row_idx, col_idx)) } else { None })
}).unwrap();
grid[robot_pos.0 as usize][robot_pos.1 as usize] = TileObject::Empty;
// println!("GRID ({}, {})", grid_height, grid_width);
// println!("ROBOT ({}, {})", robot_pos.0, robot_pos.1);
for m in moves {
let new_row = (robot_pos.0 as isize + m.0) as usize;
let new_col = (robot_pos.1 as isize + m.1) as usize;
let next_pos = &grid[new_row][new_col];
match next_pos {
TileObject::Empty => {
robot_pos = (new_row, new_col);
// print!("M");
},
TileObject:: Box => {
if let Some(next_open_space) = get_next_open_space(&grid, robot_pos, m) {
grid[new_row][new_col] = TileObject::Empty;
grid[next_open_space.0][next_open_space.1] = TileObject::Box;
robot_pos = (new_row, new_col);
// print!("~");
} else {
// print!("!");
}
},
_ => {
// print!("!");
}
}
}
let calc_score = |row_idx, col_idx| 100 * row_idx + col_idx;
let gps_score = grid.iter().enumerate().fold(0, |total, (row_idx, row)| {
total + row.iter().enumerate().fold(0, |sub_total, (col_idx, tile)| {
sub_total + if *tile == TileObject::Box { calc_score(row_idx, col_idx) } else { 0 }
})
});
Some(gps_score as u32)
}
pub fn part_two(_input: &str) -> Option<u32> {
None
}
fn get_next_open_space(grid: &[Vec<TileObject>], pos: (usize, usize), m: (isize, isize)) -> Option<(usize, usize)> {
let new_row = (pos.0 as isize + m.0) as usize;
let new_col = (pos.1 as isize + m.1) as usize;
let tile = &grid[new_row][new_col];
match tile {
TileObject::Empty => Some((new_row, new_col)),
TileObject::Box => get_next_open_space(grid, (new_row, new_col), m),
_ => None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(10092));
}
#[test]
fn test_part_one_2() {
let result = part_one(&advent_of_code::template::read_file_part("examples", DAY, 2));
assert_eq!(result, Some(2028));
}
#[ignore]
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, None);
}
}