Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use warnings;
- use List::Priority;
- $| = 1;
- use List::AllUtils qw(pairwise any);
- my @dirs = ([-1,0], [1,0], [0,-1], [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] );
- my $time = 0;
- queue:
- while (my $state = $queue->shift) {
- my ($risk, $y, $x) = @$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 $move (map { [pairwise {$a + $b} @{[$y,$x]}, @$_] } @dirs) {
- next move if (any { $_ < 0 || $_ > $max } @$move);
- my $new_risk = $risk + $grid[$move->[0]][$move->[1]];
- $queue->insert( $new_risk, [$new_risk, $move->[0], $move->[1]] );
- }
- }
Add Comment
Please, Sign In to add comment