Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use warnings;
- use List::Priority;
- my @dirs = ([1,0], [0,1], [-1,0], [0,-1]);
- my @grid = map { chomp; [split //] } <>;
- my $max = scalar( @grid ) - 1;
- # Ugly building of map for part 2
- # Build out horizontally
- foreach my $y (0 .. $max) {
- push( @{$grid[$y]}, map {my $i = $_; map { ($_ + $i - 1) % 9 + 1 } @{$grid[$y]}} (1 .. 4) );
- }
- # Build out vertically
- foreach my $i (1 .. 4) {
- foreach my $y (0 .. $max) {
- push( @grid, [map { ($_ + $i - 1) % 9 + 1 } @{$grid[$y]}] );
- }
- }
- # adjust max for new map
- $max = scalar( @grid ) - 1;
- # Same Dijkstra search as part 1
- my @visit = map { [(~0) x ($max + 1)] } (1 .. ($max + 1));
- my $queue = new List::Priority;
- $queue->insert( 0, [0,0,0,-1] );
- my $time = 0;
- queue:
- while (my $state = $queue->shift) {
- my ($risk, $y, $x, $back) = @$state;
- print ::stderr "Risk: $risk\r" if ($time++ % 50000 == 0);
- if ($y == $x == $max) {
- print "Part 2: $risk\n";
- last queue;
- }
- next queue if ($visit[$y][$x] <= $risk);
- $visit[$y][$x] = $risk;
- move:
- foreach my $d (0 .. 3) {
- next move if ($d == $back);
- my $my = $y + $dirs[$d][0];
- my $mx = $x + $dirs[$d][1];
- if (0 <= $my <= $max && 0 <= $mx <= $max) {
- my $new_risk = $risk + $grid[$mx][$my];
- $queue->insert( $new_risk, [$new_risk, $my, $mx, ($d + 2) % 4] );
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement