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()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_grid(grid: &[[u32; 10]; 10]) {
|
fn _display_grid(grid: &[[u32; 10]; 10]) {
|
||||||
for i in 0..grid.len() {
|
for i in 0..grid.len() {
|
||||||
for j in 0..grid[i].len() {
|
for j in 0..grid[i].len() {
|
||||||
print!("{:X}", grid[i][j]);
|
print!("{:X}", grid[i][j]);
|
||||||
|
87
src/day15.rs
87
src/day15.rs
@ -6,7 +6,36 @@ use priority_queue::PriorityQueue;
|
|||||||
pub struct Grid {
|
pub struct Grid {
|
||||||
rows: u32,
|
rows: u32,
|
||||||
cols: 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 {
|
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());
|
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 {
|
fn find_shortest_path_cost(grid: &Grid) -> u32 {
|
||||||
let mut total_costs: HashMap<(u32, u32), u32> = HashMap::new();
|
let mut total_costs: HashMap<(u32, u32), u32> = HashMap::new();
|
||||||
let mut min_pq: PriorityQueue<(u32, u32), i32> = PriorityQueue::new();
|
let mut min_pq: PriorityQueue<(u32, u32), i32> = PriorityQueue::new();
|
||||||
let mut visited: HashSet<(u32, u32)> = HashSet::new();
|
let mut visited: HashSet<(u32, u32)> = HashSet::new();
|
||||||
let neighbour_offsets = [
|
let neighbour_offsets = [ (0, 1), (0, -1), (1, 0), (-1, 0) ];
|
||||||
(0, 1),
|
|
||||||
(0, -1),
|
|
||||||
(1, 0),
|
|
||||||
(-1, 0)
|
|
||||||
];
|
|
||||||
min_pq.push((0, 0), 0);
|
min_pq.push((0, 0), 0);
|
||||||
total_costs.insert((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;
|
let new_smallest = min_pq.pop().unwrap().0;
|
||||||
visited.insert(new_smallest);
|
visited.insert(new_smallest);
|
||||||
|
|
||||||
for offset in neighbour_offsets {
|
for neighbour in find_neighbours(&new_smallest, grid, &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);
|
|
||||||
|
|
||||||
if visited.contains(&neighbour) {
|
if visited.contains(&neighbour) {
|
||||||
continue;
|
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;
|
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) {
|
if alt_path < *total_costs.get(&neighbour).unwrap_or(&u32::MAX) {
|
||||||
total_costs.insert(neighbour, alt_path);
|
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 {
|
pub fn part1(grid: &Grid) -> u32 {
|
||||||
find_shortest_path_cost(grid)
|
find_shortest_path_cost(grid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn part2(grid: &mut Grid) -> u32 {
|
||||||
|
grid.scale = 5;
|
||||||
|
find_shortest_path_cost(grid)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -87,4 +121,21 @@ mod tests {
|
|||||||
let result = part1(&grid);
|
let result = part1(&grid);
|
||||||
assert_eq!(result, 40);
|
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.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
||||||
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
||||||
"15.1" => println!("{}", day15::part1(&day15::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)
|
_ => println!("Day {} part {} not found", day, part)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user