Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use warnings;
- use feature qw(say);
- use Array::Heap::PriorityQueue::Numeric;
- # Read in grid, adding sentinel 0s to right and bottom
- my @Grid = map { chomp; [map {int} split(//), 0] } <>;
- push( @Grid, [(0) x $Grid[0]->@*] );
- my @Dirs = ([1,0], [0,1], [-1,0], [0,-1]);
- my $EndY = $#Grid - 1;
- my $EndX = $Grid[0]->$#* - 1;
- sub print_grid { say "\t", join( '', @$_ ) foreach (@Grid); }
- my @visit;
- my $queue = new Array::Heap::PriorityQueue::Numeric;
- $queue->add( [0, 0, 0, 0], 0 );
- $queue->add( [0, 0, 0, 1], 0 );
- my $time = 0;
- QUEUE:
- while (my $state = $queue->get) {
- my ($cool, $y, $x, $dir) = @$state;
- if ($y == $EndY and $x == $EndX) {
- say "\nPart 2: $cool";
- last QUEUE;
- }
- print ::stderr "[$time] Cooling: $cool (", $queue->size(), ") \r" if (++$time % 100000 == 0);
- # Doesn't matter which direction we come from, only the parity (vert/horz) we go out:
- my $parity = $dir % 2;
- next QUEUE if (defined $visit[$y][$x][$parity] and $cool >= $visit[$y][$x][$parity]);
- $visit[$y][$x][$parity] = $cool;
- foreach my $turn (($dir + 1) % 4, ($dir - 1) % 4) {
- my $new_y = $y;
- my $new_x = $x;
- my $new_cool = $cool;
- # Manhattan distance (End is lower right, so no absolute needed)
- my $dist = $EndY - $new_y + $EndX - $new_x;
- my $delta = ($turn >= 2) ? 1 : -1;
- STEP:
- foreach my $steps (1 .. 10) {
- $new_y += $Dirs[$turn][0];
- $new_x += $Dirs[$turn][1];
- $dist += $delta;
- my $cooling = $Grid[$new_y][$new_x];
- last STEP if ($cooling == 0);
- $new_cool += $cooling;
- next STEP if ($steps < 4);
- $queue->add( [$new_cool, $new_y, $new_x, $turn], $new_cool + $dist );
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement