diff --git a/src/day11.rs b/src/day11.rs index 1a8092b..fc3b915 100644 --- a/src/day11.rs +++ b/src/day11.rs @@ -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]); diff --git a/src/day15.rs b/src/day15.rs index 9d4e3e5..ab55a5e 100644 --- a/src/day15.rs +++ b/src/day15.rs @@ -6,7 +6,36 @@ use priority_queue::PriorityQueue; pub struct Grid { rows: u32, cols: u32, - data: Vec + data: Vec, + scale: u32 +} + +impl Grid { + fn new(rows: u32, cols: u32, data: Vec) -> 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); + } } + diff --git a/src/main.rs b/src/main.rs index 89b4fb6..fcd6491 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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) } }