feat: solve day 15 part 2
This commit is contained in:
parent
505b068c0b
commit
b0fdf15e92
@ -12,7 +12,7 @@ pub fn parse_input(input: &str) -> [[u32; 10]; 10] {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn display_grid(grid: &[[u32; 10]; 10]) {
|
||||
fn _display_grid(grid: &[[u32; 10]; 10]) {
|
||||
for i in 0..grid.len() {
|
||||
for j in 0..grid[i].len() {
|
||||
print!("{:X}", grid[i][j]);
|
||||
|
87
src/day15.rs
87
src/day15.rs
@ -6,7 +6,36 @@ use priority_queue::PriorityQueue;
|
||||
pub struct Grid {
|
||||
rows: u32,
|
||||
cols: u32,
|
||||
data: Vec<u32>
|
||||
data: Vec<u32>,
|
||||
scale: u32
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
fn new(rows: u32, cols: u32, data: Vec<u32>) -> Grid {
|
||||
return Grid {
|
||||
rows, cols, data,
|
||||
scale: 1
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, point: &(u32, u32)) -> u32 {
|
||||
let row = point.0 % self.rows;
|
||||
let col = point.1 % self.cols;
|
||||
let value = self.data[(row * self.cols + col) as usize];
|
||||
return (value + point.0 / self.rows + point.1 / self.cols - 1) % 9 + 1;
|
||||
}
|
||||
|
||||
fn width(&self) -> u32 {
|
||||
self.cols * self.scale
|
||||
}
|
||||
|
||||
fn height(&self) -> u32 {
|
||||
self.rows * self.scale
|
||||
}
|
||||
|
||||
fn within_bounds(&self, point: &(i32, i32)) -> bool {
|
||||
point.0 >= 0 && point.1 >= 0 && point.0 < self.height() as i32 && point.1 < self.width() as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Grid {
|
||||
@ -20,19 +49,26 @@ pub fn parse_input(input: &str) -> Grid {
|
||||
data.push(c.to_digit(10).unwrap());
|
||||
}
|
||||
}
|
||||
return Grid { rows, cols, data };
|
||||
return Grid::new(rows, cols, data);
|
||||
}
|
||||
|
||||
fn find_neighbours(pos: &(u32, u32), grid: &Grid, offsets: &[(i32, i32)]) -> Vec<(u32, u32)> {
|
||||
let mut neighbours = Vec::new();
|
||||
for offset in offsets {
|
||||
let row = pos.0 as i32 + offset.0;
|
||||
let col = pos.1 as i32 + offset.1;
|
||||
if grid.within_bounds(&(row, col)) {
|
||||
neighbours.push((row as u32, col as u32));
|
||||
}
|
||||
}
|
||||
return neighbours;
|
||||
}
|
||||
|
||||
fn find_shortest_path_cost(grid: &Grid) -> u32 {
|
||||
let mut total_costs: HashMap<(u32, u32), u32> = HashMap::new();
|
||||
let mut min_pq: PriorityQueue<(u32, u32), i32> = PriorityQueue::new();
|
||||
let mut visited: HashSet<(u32, u32)> = HashSet::new();
|
||||
let neighbour_offsets = [
|
||||
(0, 1),
|
||||
(0, -1),
|
||||
(1, 0),
|
||||
(-1, 0)
|
||||
];
|
||||
let neighbour_offsets = [ (0, 1), (0, -1), (1, 0), (-1, 0) ];
|
||||
min_pq.push((0, 0), 0);
|
||||
total_costs.insert((0, 0), 0);
|
||||
|
||||
@ -40,19 +76,12 @@ fn find_shortest_path_cost(grid: &Grid) -> u32 {
|
||||
let new_smallest = min_pq.pop().unwrap().0;
|
||||
visited.insert(new_smallest);
|
||||
|
||||
for offset in neighbour_offsets {
|
||||
let neighbour_row = new_smallest.0 as i32 + offset.0;
|
||||
let neighbour_col = new_smallest.1 as i32 + offset.1;
|
||||
if !(neighbour_row >= 0 && neighbour_col >= 0 && neighbour_row < grid.rows as i32 && neighbour_col < grid.cols as i32) {
|
||||
continue;
|
||||
}
|
||||
let neighbour = (neighbour_row as u32, neighbour_col as u32);
|
||||
|
||||
for neighbour in find_neighbours(&new_smallest, grid, &neighbour_offsets) {
|
||||
if visited.contains(&neighbour) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let alt_distance = grid.data[(neighbour_row as u32 * grid.cols + neighbour_col as u32) as usize];
|
||||
let alt_distance = grid.get(&neighbour);
|
||||
let alt_path = total_costs.get(&new_smallest).unwrap_or(&u32::MAX) + alt_distance;
|
||||
if alt_path < *total_costs.get(&neighbour).unwrap_or(&u32::MAX) {
|
||||
total_costs.insert(neighbour, alt_path);
|
||||
@ -61,13 +90,18 @@ fn find_shortest_path_cost(grid: &Grid) -> u32 {
|
||||
}
|
||||
}
|
||||
|
||||
return *total_costs.get(&(grid.rows-1, grid.cols-1)).unwrap();
|
||||
return *total_costs.get(&(grid.height()-1, grid.width()-1)).unwrap();
|
||||
}
|
||||
|
||||
pub fn part1(grid: &Grid) -> u32 {
|
||||
find_shortest_path_cost(grid)
|
||||
}
|
||||
|
||||
pub fn part2(grid: &mut Grid) -> u32 {
|
||||
grid.scale = 5;
|
||||
find_shortest_path_cost(grid)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -87,4 +121,21 @@ mod tests {
|
||||
let result = part1(&grid);
|
||||
assert_eq!(result, 40);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
let mut grid = parse_input("1163751742
|
||||
1381373672
|
||||
2136511328
|
||||
3694931569
|
||||
7463417111
|
||||
1319128137
|
||||
1359912421
|
||||
3125421639
|
||||
1293138521
|
||||
2311944581");
|
||||
let result = part2(&mut grid);
|
||||
assert_eq!(result, 315);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,7 @@ fn run(day: i32, part: i32, input_filename: &str) {
|
||||
"14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
||||
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
||||
"15.1" => println!("{}", day15::part1(&day15::parse_input(&contents))),
|
||||
"15.2" => println!("{}", day15::part2(&mut day15::parse_input(&contents))),
|
||||
_ => println!("Day {} part {} not found", day, part)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user