Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use warnings;
- use feature qw(say);
- $| = 1;
- #use constant GRID_SIZE => 7;
- #use constant TIME => 12;
- use constant GRID_SIZE => 71;
- use constant TIME => 1024;
- use Math::Vector::Real;
- my ($vy,$vx) = Math::Vector::Real->canonical_base(2);
- my @Dirs = ($vy, $vx, -$vy, -$vx);
- # Make grid, adding sentinel ~s to right and bottom
- my @Grid = map { [('.') x GRID_SIZE, '~'] } (1 .. GRID_SIZE);
- push( @Grid, [('~') x GRID_SIZE] );
- sub grid_at ($) { my $p = shift; return ($Grid[$p->[1]][$p->[0]]) }
- sub print_grid { say "\t", join( '', @$_ ) foreach (@Grid); }
- # Grabbing just the numbers
- my @input = map { V(m#(\d+)#g) } <>;
- # Drop up to TIME to start:
- $Grid[$_->[1]][$_->[0]] = '#' foreach (@input[0 .. TIME-1]);
- # Get hash of route from upper-left to lower right
- sub get_route {
- my @queue = ([V(0,0), []]);
- my %visit;
- my $end = V(GRID_SIZE - 1, GRID_SIZE - 1);
- while (my $state = shift @queue) {
- my ($pos, $path) = @$state;
- return (map {$_ => 1} @$path) if ($pos == $end);
- next if ($visit{$pos}++);
- # Add legal moves to queue
- push(@queue, [$_, [@$path, $_]]) foreach (grep {grid_at($_) eq '.'} map {$pos + $_} @Dirs);
- }
- return ();
- }
- # Get route through initial drop for part 1:
- my %path = &get_route;
- say "Part 1: ", scalar keys %path;
- # Part 2: drop until current route blocked, then get new route (until impossible)
- for (my $t = TIME; $t < @input; $t++) {
- my $pos = $input[$t];
- $Grid[$pos->[1]][$pos->[0]] = '#';
- next if (!exists $path{$pos}); # fell off the path, still unblocked
- print ::stderr "[$t] $pos \r";
- # Find new path
- %path = &get_route;
- if (!scalar keys %path) {
- say "\nPart 2: $pos->[0],$pos->[1]";
- last;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement