Advertisement
musifter

AoC 2023 day 17, part 1 (Perl)

Dec 17th, 2023 (edited)
900
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.73 KB | Source Code | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use feature         qw(say);
  7.  
  8. use Array::Heap::PriorityQueue::Numeric;
  9. use Math::Vector::Real;
  10.  
  11. my ($Y,$X) = Math::Vector::Real->canonical_base(2);
  12. my @Dirs = ($Y, $X, -$Y, -$X);
  13.  
  14. # Read in grid, adding sentinel 0s to right and bottom
  15. my @Grid = map { chomp; [map {int} split(//), 0] } <>;
  16. push( @Grid, [(0) x $Grid[0]->@*] );
  17. my $End = V($#Grid - 1, $Grid[0]->$#* - 1);
  18.  
  19. sub grid_at ($) { my $p = shift; return ($Grid[$p->[0]][$p->[1]]) }
  20. sub print_grid  { say "\t", join( '', @$_ ) foreach (@Grid); }
  21.  
  22. my %visit;
  23. my $queue = new Array::Heap::PriorityQueue::Numeric;
  24. $queue->add( [0, V(0,0), 0], 0 );
  25. $queue->add( [0, V(0,0), 1], 0 );
  26.  
  27. my $time = 0;
  28.  
  29. QUEUE:
  30. while (my $state = $queue->get) {
  31.     my ($cool, $pos, $dir) = @$state;
  32.  
  33.     if ($pos == $End) {
  34.         say "\nPart 1: $cool";
  35.         last QUEUE;
  36.     }
  37.  
  38.     print ::stderr "[$time] Cooling: $cool (", $queue->size(), ")  \r"  if (++$time % 50000 == 0);
  39.  
  40.     next QUEUE  if (exists $visit{$pos,$dir} and $cool >= $visit{$pos,$dir});
  41.     $visit{$pos,$dir} = $cool;
  42.  
  43.     foreach my $turn (($dir + 1) % 4, ($dir - 1) % 4) {
  44.         my $new_pos  = $pos;
  45.         my $new_cool = $cool;
  46.  
  47.         my $dist  = $pos->manhattan_dist($End);
  48.         my $delta = ($turn >= 2) ? 1 : -1;
  49.  
  50.         STEP:
  51.         foreach my $steps (1 .. 3) {
  52.             $new_pos += $Dirs[$turn];
  53.             $dist += $delta;
  54.  
  55.             my $cooling = grid_at( $new_pos );
  56.             last STEP if ($cooling == 0);
  57.  
  58.             $new_cool += $cooling;
  59.             next STEP if (exists $visit{$new_pos,$turn} and $new_cool >= $visit{$new_pos,$turn});
  60.  
  61.             $queue->add( [$new_cool, $new_pos, $turn], $new_cool + $dist );
  62.         }
  63.     }
  64. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement