Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use warnings;
- use List::AllUtils qw(max pairwise);
- sub vec_sum ($$) { return [pairwise {$a + $b} @{$_[0]}, @{$_[1]}] }
- sub vec_step ($$) { return [pairwise {$b <=> $a} @{$_[0]}, @{$_[1]}] }
- sub point_eq ($$) { return ($_[0]->[0] == $_[1]->[0] and $_[0]->[1] == $_[1]->[1]) }
- my %grid;
- my $maxY = 0;
- # Read in rock structure:
- foreach (<>) {
- my @corners = map { [m#(\d+)#g] } m#(\d+,\d+)#g;
- my $pos = shift @corners;
- $grid{ $pos->[0], $pos->[1] } = '#';
- $maxY = max ($maxY, $pos->[1]);
- while (my $next = shift @corners) {
- my $delta = vec_step( $pos, $next );
- do {
- $pos = vec_sum( $pos, $delta );
- $grid{ $pos->[0], $pos->[1] } = '#';
- } until (point_eq( $pos, $next ));
- $maxY = max ($maxY, $pos->[1]);
- }
- }
- $maxY += 1; # add in space to infinite floor
- my @prec = ([0,1], [-1,1], [1,1]); # falling order of precedence
- my @path = ([500,0]); # track last fallen path to avoid redoing
- my $part1;
- my $sand = 0;
- while (my $pos = pop @path) {
- my ($px,$py) = @$pos;
- DROP:
- while ($py < $maxY) {
- foreach my $fall (@prec) {
- my ($nx,$ny) = ($px + $fall->[0], $py + $fall->[1]);
- if (!$grid{$nx, $ny}) {
- push( @path, [$px,$py] );
- ($px,$py) = ($nx,$ny);
- next DROP;
- }
- }
- last DROP;
- }
- $grid{$px, $py} = 'o';
- $part1 //= $sand if ($py == $maxY);
- $sand++;
- }
- print "Part 1: $part1\n";
- print "Part 2: $sand\n";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement