75 lines
1.5 KiB
Perl
75 lines
1.5 KiB
Perl
|
|
||
|
use 5.36.0;
|
||
|
use lib '.';
|
||
|
|
||
|
use DDP;
|
||
|
|
||
|
use Part1;
|
||
|
|
||
|
package Part2;
|
||
|
|
||
|
use Math::Vector::Real;
|
||
|
use List::AllUtils qw/ uniq /;
|
||
|
|
||
|
my @directions = map { V(@$_) } [ -1, 0 ], [ 0, 1 ], [ 1, 0 ], [ 0, -1 ];
|
||
|
|
||
|
sub copy_grid ($grid) {
|
||
|
return [ map { [@$_] } @$grid ];
|
||
|
}
|
||
|
|
||
|
sub add_vectors($x,$y) {
|
||
|
return [ $x->[0]+$y->[0],$x->[1]+$y->[1]];
|
||
|
}
|
||
|
|
||
|
sub do_the_round ($grid) {
|
||
|
my $guard = Part1::find_guard($grid);
|
||
|
my $current_direction = 0;
|
||
|
|
||
|
my %seen;
|
||
|
|
||
|
my $loop = 0;
|
||
|
|
||
|
while () {
|
||
|
my $ahead = $guard + $directions[$current_direction];
|
||
|
last unless Part1::inside_grid( $grid, $ahead );
|
||
|
if ( $grid->[ $ahead->[0] ][ $ahead->[1] ] eq '#' ) {
|
||
|
$current_direction++;
|
||
|
$current_direction %= @directions;
|
||
|
redo;
|
||
|
}
|
||
|
$guard = $ahead;
|
||
|
if ( $seen{"$guard"}{$current_direction} ) {
|
||
|
$loop = 1;
|
||
|
last;
|
||
|
}
|
||
|
$seen{"$guard"}{$current_direction}++;
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
loop => $loop,
|
||
|
seen => [
|
||
|
keys %seen
|
||
|
]
|
||
|
};
|
||
|
}
|
||
|
|
||
|
sub solve ($grid) {
|
||
|
my $guard = Part1::find_guard($grid);
|
||
|
my $current_direction = 0;
|
||
|
|
||
|
my $r = do_the_round($grid);
|
||
|
|
||
|
my $loops = 0;
|
||
|
|
||
|
for my $loc ( grep { $grid->[ $_->[0] ][ $_->[1] ] ne '^' }
|
||
|
map { [/(\d+)/g] } $r->{seen}->@* ) {
|
||
|
my $copy = copy_grid($grid);
|
||
|
$copy->[ $loc->[0] ][ $loc->[1] ] = '#';
|
||
|
$loops++ if do_the_round($copy)->{loop};
|
||
|
}
|
||
|
|
||
|
return $loops;
|
||
|
}
|
||
|
|
||
|
1;
|