Advertisement
musifter

AoC 2024, day 18 (Perl)

Dec 17th, 2024 (edited)
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.82 KB | Source Code | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. use feature         qw(say);
  6.  
  7. $| = 1;
  8.  
  9. #use constant GRID_SIZE => 7;
  10. #use constant TIME => 12;
  11. use constant GRID_SIZE => 71;
  12. use constant TIME => 1024;
  13.  
  14. use Math::Vector::Real;
  15.  
  16. my ($vy,$vx) = Math::Vector::Real->canonical_base(2);
  17. my @Dirs = ($vy, $vx, -$vy, -$vx);
  18.  
  19. # Make grid, adding sentinel ~s to right and bottom
  20. my @Grid = map { [('.') x GRID_SIZE, '~'] } (1 .. GRID_SIZE);
  21. push( @Grid, [('~') x GRID_SIZE] );
  22.  
  23. sub grid_at ($) { my $p = shift; return ($Grid[$p->[1]][$p->[0]]) }
  24. sub print_grid  { say "\t", join( '', @$_ ) foreach (@Grid); }
  25.  
  26. # Grabbing just the numbers
  27. my @input = map { V(m#(\d+)#g) } <>;
  28.  
  29. # Drop up to TIME to start:
  30. $Grid[$_->[1]][$_->[0]] = '#'  foreach (@input[0 .. TIME-1]);
  31.  
  32. # Get hash of route from upper-left to lower right
  33. sub get_route {
  34.     my @queue = ([V(0,0), []]);
  35.  
  36.     my %visit;
  37.     my $end = V(GRID_SIZE - 1, GRID_SIZE - 1);
  38.  
  39.     while (my $state = shift @queue) {
  40.         my ($pos, $path) = @$state;
  41.  
  42.         return (map {$_ => 1} @$path) if ($pos == $end);
  43.  
  44.         next if ($visit{$pos}++);
  45.  
  46.         # Add legal moves to queue
  47.         push(@queue, [$_, [@$path, $_]]) foreach (grep {grid_at($_) eq '.'} map {$pos + $_} @Dirs);
  48.     }
  49.     return ();
  50. }
  51.  
  52. # Get route through initial drop for part 1:
  53. my %path = &get_route;
  54. say "Part 1: ", scalar keys %path;
  55.  
  56. # Part 2: drop until current route blocked, then get new route (until impossible)
  57. for (my $t = TIME; $t < @input; $t++) {
  58.     my $pos = $input[$t];
  59.     $Grid[$pos->[1]][$pos->[0]] = '#';
  60.  
  61.     next if (!exists $path{$pos});      # fell off the path, still unblocked
  62.  
  63.     print ::stderr "[$t] $pos  \r";
  64.  
  65.     # Find new path
  66.     %path = &get_route;
  67.     if (!scalar keys %path) {
  68.         say "\nPart 2: $pos->[0],$pos->[1]";
  69.         last;
  70.     }
  71. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement