adventofcode/2020/16/part2.pm

88 lines
1.6 KiB
Perl

package part2;
use 5.20.0;
use warnings;
use List::AllUtils qw/ pairmap zip product /;
use Range::Merge qw/ merge /;
use Set::Object qw/ set /;
require './part1.pm';
use experimental qw/ signatures postderef /;
sub inRanges($n, $ranges) {
for (@$ranges) {
return 1 if $_->[0] <= $n and $_->[1] >= $n;
}
return 0;
}
sub possibilities($n,$fields) {
return set(
grep { inRanges($n, $fields->{$_})} keys %$fields
)
}
sub solution($input) {
my ( $fields, $myticket, $tickets ) = split "\n\n", $input;
my %fields = map {
my ( $name, $ranges) = split ':';
$name => merge([ map { [ split '-'] } $ranges =~ /(\d+-\d+)/g ])
} split "\n", $fields;
my @global;
for my $ticket ( split "\n", $tickets ) {
next if $ticket =~ /nearby/;
my @fields = split ',', $ticket;
@fields = map { possibilities($_,\%fields) } @fields;
next if grep { not $_->size } @fields;
if(!@global) {
@global = @fields;
}
else {
@global = pairmap { $a*$b } zip @global, @fields;
}
}
use DDP; say join " ", @$_ for @global;
my %indexes;
LOOP: while() {
for( 0..$#global ) {
if( $global[$_]->size == 1 ) {
my $e = $global[$_];
$indexes{$global[$_][0]} = $_;
@global = map { $_ - $e } @global;
redo LOOP;
}
}
last LOOP;
}
p %indexes;
my @myt = $myticket =~ /(\d+)/g;
return product
@myt[
map { $indexes{$_} }
grep { /departure/ } keys %indexes ];
}
1;