Advertisement
musifter

AoC 2022, day 14 (Perl)

Dec 14th, 2022
1,585
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.61 KB | Source Code | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use List::AllUtils   qw(max pairwise);
  7.  
  8. sub vec_sum ($$)  { return [pairwise {$a + $b}   @{$_[0]}, @{$_[1]}] }
  9. sub vec_step ($$) { return [pairwise {$b <=> $a} @{$_[0]}, @{$_[1]}] }
  10. sub point_eq ($$) { return ($_[0]->[0] == $_[1]->[0] and $_[0]->[1] == $_[1]->[1]) }
  11.  
  12. my %grid;
  13. my $maxY = 0;
  14.  
  15. # Read in rock structure:
  16. foreach (<>) {
  17.     my @corners = map { [m#(\d+)#g] } m#(\d+,\d+)#g;
  18.  
  19.     my $pos = shift @corners;
  20.     $grid{ $pos->[0], $pos->[1] } = '#';
  21.  
  22.     $maxY = max ($maxY, $pos->[1]);
  23.  
  24.     while (my $next = shift @corners) {
  25.         my $delta = vec_step( $pos, $next );
  26.  
  27.         do {
  28.             $pos = vec_sum( $pos, $delta );
  29.             $grid{ $pos->[0], $pos->[1] } = '#';
  30.         } until (point_eq( $pos, $next ));
  31.  
  32.         $maxY = max ($maxY, $pos->[1]);
  33.     }
  34. }
  35.  
  36. $maxY += 1;                         # add in space to infinite floor
  37. my @prec = ([0,1], [-1,1], [1,1]);  # falling order of precedence
  38.  
  39. my @path = ([500,0]);               # track last fallen path to avoid redoing
  40. my $part1;
  41. my $sand = 0;
  42.  
  43. while (my $pos = pop @path) {
  44.     my ($px,$py) = @$pos;
  45.  
  46.     DROP:
  47.     while ($py < $maxY) {
  48.         foreach my $fall (@prec) {
  49.             my ($nx,$ny) = ($px + $fall->[0], $py + $fall->[1]);
  50.  
  51.             if (!$grid{$nx, $ny}) {
  52.                 push( @path, [$px,$py] );
  53.                 ($px,$py) = ($nx,$ny);
  54.                 next DROP;
  55.             }
  56.         }
  57.         last DROP;
  58.     }
  59.  
  60.     $grid{$px, $py} = 'o';
  61.     $part1 //= $sand if ($py == $maxY);
  62.     $sand++;
  63. }
  64.  
  65. print "Part 1: $part1\n";
  66. print "Part 2: $sand\n";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement