Advertisement
musifter

AoC 2022 day 12 (Perl)

Dec 12th, 2022 (edited)
1,869
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 2.06 KB | Source Code | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use v5.12;
  4. use warnings;
  5.  
  6. my @dirs = ([0, 1], [0, -1], [1, 0], [-1, 0]);
  7.  
  8. # Read in grid and put a ring of '~' around it
  9. my @grid = map { chomp; [ '~', split( // ), '~' ] } <>;
  10.  
  11. my $MAX_X = scalar @{$grid[0]};
  12.  
  13. unshift( @grid, [split //, ('~' x $MAX_X)] );
  14. push( @grid, [split //, ('~' x $MAX_X)] );
  15.  
  16. my $MAX_Y = scalar @grid;
  17.  
  18. # Find start and end points (and change them to their heights)
  19. my $start;
  20. my $end;
  21.  
  22. foreach my $y (1 .. $MAX_Y - 2) {
  23.     foreach my $x (1 .. $MAX_X - 2) {
  24.         if ($grid[$y][$x] eq 'S') {
  25.             $start = [$y,$x];
  26.             $grid[$y][$x] = 'a';
  27.         }
  28.  
  29.         if ($grid[$y][$x] eq 'E') {
  30.             $end = [$y,$x];
  31.             $grid[$y][$x] = 'z';
  32.         }
  33.  
  34.         last if ($start && $end);
  35.     }
  36. }
  37.  
  38. # Path finding routine:
  39. # - starts at $start
  40. # - uses &$found_end( pos ) to detect if at end
  41. # - uses &$good_height( current, move ) to tell if move is valid
  42. sub find_path {
  43.     my ($start, $found_end, $good_height) = @_;
  44.  
  45.     my @visited;
  46.     my @queue = ( [0, $start] );
  47.  
  48.     while (my $state = shift @queue) {
  49.         my ($time, $pos) = @$state;
  50.  
  51.         return ($time)  if (&$found_end( $pos->[0], $pos->[1] ));
  52.         next            if ($visited[$pos->[0]][$pos->[1]]++);
  53.  
  54.         my $height = ord( $grid[$pos->[0]][$pos->[1]] );
  55.  
  56.         foreach my $d (@dirs) {
  57.             my $move = [$pos->[0] + $d->[0], $pos->[1] + $d->[1]];
  58.             my $move_height = ord( $grid[$move->[0]][$move->[1]] );
  59.  
  60.             if (&$good_height( $height, $move_height )) {
  61.                 push( @queue, [$time + 1, $move] );
  62.             }
  63.         }
  64.     }
  65. }
  66.  
  67. say "Part 1: ", &find_path( $start,
  68.                             sub {$_[0] == $end->[0] && $_[1] == $end->[1]},  # find end
  69.                             sub {$_[0] + 1 >= $_[1]} );                      # going up
  70.  
  71. say "Part 2: ", &find_path( $end,
  72.                             sub {$grid[$_[0]][$_[1]] eq 'a'},                # find a
  73.                             sub {$_[0] - 1 <= $_[1] <= ord('z')} );          # going down
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement