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);
- use List::Util qw(max any);
- use Math::Vector::Real;
- my ($Y,$X) = Math::Vector::Real->canonical_base(2);
- my @Dir = ($Y, $X, -$Y, -$X); # SENW (0123)
- my %Piece = (
- '|' => [ [0], [0,2], [2], [0,2]],
- '-' => [[1,3], [1], [1,3], [3]],
- '\\' => [[1], [0], [3], [2]],
- '/' => [[3], [2], [1], [0]],
- '.' => [[0], [1], [2], [3]],
- '~' => [[], [], [], []],
- );
- # Read in grid, adding sentinel ~s to right and bottom
- my @Grid = map { chomp; [split(//), '~'] } <>;
- push( @Grid, [('~') x $Grid[0]->@*] );
- sub grid_at ($) { my $p = shift; return ($Grid[$p->[0]][$p->[1]]) }
- sub print_grid { say "\t", join( '', @$_ ) foreach (@Grid); }
- sub energize {
- my ($start, $start_dir) = @_;
- my %visit;
- my @queue = ([$start, $start_dir]);
- my $count = 0;
- BEAM:
- while (my $state = shift @queue) {
- my ($pos, $dir) = @$state;
- next BEAM if (exists $visit{$pos} and any {$_ == $dir} $visit{$pos}->@*);
- next BEAM if (grid_at($pos) eq '~');
- $count++ if (!exists $visit{$pos});
- push( $visit{$pos}->@*, $dir );
- foreach my $move ($Piece{grid_at($pos)}[$dir]->@*) {
- push( @queue, [$pos + $Dir[$move], $move] );
- }
- }
- return ($count);
- }
- my @col;
- foreach my $i (0 .. $#Grid) {
- print ::stderr "Pos: $i\r";
- push( @col, &energize( V(0,$i), 0 ) );
- push( @col, &energize( V($#Grid - 1, $i), 2 ) );
- push( @col, &energize( V($i,0), 1 ) );
- push( @col, &energize( V($i, $#Grid - 1), 3 ) );
- }
- say "\nPart 1: ", $col[2];
- say "Part 2: ", max( @col );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement