Advertisement
musifter

AoC 2023 day 17, part 2 (Perl)

Dec 17th, 2023 (edited)
971
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.86 KB | Source Code | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use feature         qw(say);
  7. use Array::Heap::PriorityQueue::Numeric;
  8.  
  9. # Read in grid, adding sentinel 0s to right and bottom
  10. my @Grid = map { chomp; [map {int} split(//), 0] } <>;
  11. push( @Grid, [(0) x $Grid[0]->@*] );
  12.  
  13. my @Dirs = ([1,0], [0,1], [-1,0], [0,-1]);
  14.  
  15. my $EndY = $#Grid - 1;
  16. my $EndX = $Grid[0]->$#* - 1;
  17.  
  18. sub print_grid  { say "\t", join( '', @$_ ) foreach (@Grid); }
  19.  
  20. my @visit;
  21. my $queue = new Array::Heap::PriorityQueue::Numeric;
  22. $queue->add( [0, 0, 0, 0], 0 );
  23. $queue->add( [0, 0, 0, 1], 0 );
  24.  
  25. my $time = 0;
  26.  
  27. QUEUE:
  28. while (my $state = $queue->get) {
  29.     my ($cool, $y, $x, $dir) = @$state;
  30.  
  31.     if ($y == $EndY and $x == $EndX) {
  32.         say "\nPart 2: $cool";
  33.         last QUEUE;
  34.     }
  35.  
  36.     print ::stderr "[$time] Cooling: $cool (", $queue->size(), ")  \r"  if (++$time % 100000 == 0);
  37.  
  38.     # Doesn't matter which direction we come from, only the parity (vert/horz) we go out:
  39.     my $parity = $dir % 2;
  40.     next QUEUE  if (defined $visit[$y][$x][$parity] and $cool >= $visit[$y][$x][$parity]);
  41.     $visit[$y][$x][$parity] = $cool;
  42.  
  43.     foreach my $turn (($dir + 1) % 4, ($dir - 1) % 4) {
  44.         my $new_y    = $y;
  45.         my $new_x    = $x;
  46.         my $new_cool = $cool;
  47.  
  48.         # Manhattan distance (End is lower right, so no absolute needed)
  49.         my $dist  = $EndY - $new_y + $EndX - $new_x;
  50.         my $delta = ($turn >= 2) ? 1 : -1;
  51.  
  52.         STEP:
  53.         foreach my $steps (1 .. 10) {
  54.             $new_y += $Dirs[$turn][0];
  55.             $new_x += $Dirs[$turn][1];
  56.             $dist += $delta;
  57.  
  58.             my $cooling = $Grid[$new_y][$new_x];
  59.             last STEP if ($cooling == 0);
  60.  
  61.             $new_cool += $cooling;
  62.             next STEP if ($steps < 4);
  63.  
  64.             $queue->add( [$new_cool, $new_y, $new_x, $turn], $new_cool + $dist );
  65.         }
  66.     }
  67. }
  68.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement