Compare commits
No commits in common. "be223b6cef87a056fe2b42af15173b7bc5397337" and "b1cf1719a3a2e5f5828c946c09e633915579deee" have entirely different histories.
be223b6cef
...
b1cf1719a3
@ -4,38 +4,36 @@ package Part1;
|
|||||||
|
|
||||||
use List::AllUtils qw/ /;
|
use List::AllUtils qw/ /;
|
||||||
|
|
||||||
sub parse_input ($input) {
|
sub parse_input($input) {
|
||||||
my ( $directions, undef, @nodes ) = split "\n", $input;
|
my ( $directions, undef, @nodes ) = split "\n", $input;
|
||||||
|
|
||||||
$directions = [ split "", $directions =~ s/R/1/gr =~ s/L/0/gr ];
|
$directions = [ split "", $directions =~ s/R/1/gr =~ s/L/0/gr ];
|
||||||
|
|
||||||
my %nodes;
|
my %nodes;
|
||||||
|
|
||||||
for (@nodes) {
|
for(@nodes) {
|
||||||
my @n = /([A-Z\d]+)/g;
|
my @n = /([A-Z]+)/g;
|
||||||
$nodes{ shift @n } = \@n;
|
$nodes{ shift @n } = \@n;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
directions => $directions,
|
directions => $directions,
|
||||||
nodes => \%nodes
|
nodes => \%nodes };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub solution_1 ($input) {
|
sub solution_1 ($input) {
|
||||||
my $p = parse_input($input);
|
my $p = parse_input($input);
|
||||||
my @directions = $p->{directions}->@*;
|
my @directions = $p->{directions}->@*;
|
||||||
my %nodes = $p->{nodes}->%*;
|
my %nodes = $p->{nodes}->%*;
|
||||||
|
|
||||||
my $visited = 0;
|
my $visited = 0;
|
||||||
my $next_index = 0;
|
my $next_index = 0;
|
||||||
my $current = 'AAA';
|
my $current = 'AAA';
|
||||||
|
|
||||||
while ( $current ne 'ZZZ' ) {
|
while( $current ne 'ZZZ') {
|
||||||
$visited++;
|
$visited++;
|
||||||
|
|
||||||
$current =
|
$current = $nodes{$current}->[ $directions[$next_index++ % @directions ] ];
|
||||||
$nodes{$current}->[ $directions[ $next_index++ % @directions ] ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $visited;
|
return $visited;
|
||||||
|
117
2023/08/Part2.pm
117
2023/08/Part2.pm
@ -4,124 +4,11 @@ package Part2;
|
|||||||
|
|
||||||
use Part1;
|
use Part1;
|
||||||
|
|
||||||
use List::AllUtils qw/all first_index none min max product /;
|
use List::AllUtils qw/ /;
|
||||||
use List::UtilsBy qw/ min_by max_by /;
|
|
||||||
use Math::Utils qw/ lcm /;
|
|
||||||
|
|
||||||
sub get_cycle( $current, $directions, $nodes ) {
|
|
||||||
|
|
||||||
my @tracks;
|
|
||||||
my $next_index = 0;
|
|
||||||
|
|
||||||
while() {
|
|
||||||
my $t = join '-', $current,$next_index;
|
|
||||||
my $i = first_index { $_ eq $t } @tracks;
|
|
||||||
if( $i > -1 ) {
|
|
||||||
my $c = 0;
|
|
||||||
# p @tracks;
|
|
||||||
# warn $i, " ",$t;
|
|
||||||
return $i, map {
|
|
||||||
$c++;
|
|
||||||
if(/Z-/) {
|
|
||||||
my $x = $c; $c = 0; $x;
|
|
||||||
}else {
|
|
||||||
()
|
|
||||||
}
|
|
||||||
} splice @tracks, $i;
|
|
||||||
}
|
|
||||||
push @tracks, $t;
|
|
||||||
$current = $nodes->{$current}[ $directions->[ $next_index ] ];
|
|
||||||
$next_index = ( $next_index+1)% @$directions;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub find_z($current,$next_index,$directions,$nodes) {
|
|
||||||
|
|
||||||
my $visited = 0;
|
|
||||||
|
|
||||||
while ( ) {
|
|
||||||
$visited++;
|
|
||||||
|
|
||||||
$current =
|
|
||||||
$nodes->{$current}[ $directions->[ $next_index++ % @$directions ] ];
|
|
||||||
|
|
||||||
last if $current =~ /Z$/
|
|
||||||
}
|
|
||||||
|
|
||||||
return $visited, $current, $next_index;
|
|
||||||
}
|
|
||||||
sub speedrun($current,$next_index,$directions,$nodes,$n) {
|
|
||||||
|
|
||||||
$current =
|
|
||||||
$nodes->{$current}[ $directions->[ $next_index++ % @$directions ] ]
|
|
||||||
for 1..$n;
|
|
||||||
|
|
||||||
return $current;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub equation_for($current,$directions,$nodes) {
|
|
||||||
|
|
||||||
my $visited = 0;
|
|
||||||
my $next_index=0;
|
|
||||||
|
|
||||||
while ( ) {
|
|
||||||
$visited++;
|
|
||||||
|
|
||||||
$current =
|
|
||||||
$nodes->{$current}[ $directions->[ $next_index++ % @$directions ] ];
|
|
||||||
|
|
||||||
last if $current =~ /Z$/
|
|
||||||
}
|
|
||||||
|
|
||||||
my $first = $visited;
|
|
||||||
$visited = 0;
|
|
||||||
|
|
||||||
while ( ) {
|
|
||||||
$visited++;
|
|
||||||
|
|
||||||
$current =
|
|
||||||
$nodes->{$current}[ $directions->[ $next_index++ % @$directions ] ];
|
|
||||||
|
|
||||||
last if $current =~ /Z$/
|
|
||||||
}
|
|
||||||
|
|
||||||
my $entry = { b => $first, m => $visited };
|
|
||||||
return $entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sub solution_2 ($input) {
|
sub solution_2 ($input) {
|
||||||
my $p = Part1::parse_input($input);
|
...;
|
||||||
my @directions = $p->{directions}->@*;
|
|
||||||
my %nodes = $p->{nodes}->%*;
|
|
||||||
|
|
||||||
my $steps = 0;
|
|
||||||
my @paths = grep { /A$/ } keys %nodes;
|
|
||||||
my $next_index = 0;
|
|
||||||
|
|
||||||
my @equations = map { equation_for($_,\@directions,\%nodes) } @paths;
|
|
||||||
|
|
||||||
return lcm map { $_->{b} } @equations;
|
|
||||||
|
|
||||||
for(@equations) {
|
|
||||||
$_->{i} = 1;
|
|
||||||
$_->{total} = $_->{b}+$_->{m};
|
|
||||||
}
|
|
||||||
|
|
||||||
until( all { $_->{total} == $equations[0]->{total} } @equations ) {
|
|
||||||
my $i = max map { $_->{total} } @equations;
|
|
||||||
|
|
||||||
for(@equations) {
|
|
||||||
while( $_->{total}<$i) {
|
|
||||||
$_->{total}+=$_->{m};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# use DDP; p @equations;
|
|
||||||
}
|
|
||||||
|
|
||||||
$equations[0]->{total};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -9,8 +9,8 @@ use File::Serialize;
|
|||||||
use Part1;
|
use Part1;
|
||||||
use Part2;
|
use Part2;
|
||||||
|
|
||||||
my $day = path('.')->absolute->basename =~ s/^0//r;
|
my $day = path('.')->absolute->basename =~ s/^0//r;
|
||||||
my $year = path('.')->absolute->parent->basename;
|
my $year = path('.')->absolute->parent->basename;
|
||||||
my $solutions = deserialize_file('solutions.yml');
|
my $solutions = deserialize_file('solutions.yml');
|
||||||
|
|
||||||
my @parts = (
|
my @parts = (
|
||||||
@ -36,7 +36,6 @@ for my $part (@parts) {
|
|||||||
language => 'perl',
|
language => 'perl',
|
||||||
part => $part->{part},
|
part => $part->{part},
|
||||||
time => $res->cpu_a / $res->iters,
|
time => $res->cpu_a / $res->iters,
|
||||||
persec => $res->iters / $res->cpu_a,
|
|
||||||
timestamp => DateTime->now->iso8601,
|
timestamp => DateTime->now->iso8601,
|
||||||
};
|
};
|
||||||
say to_json $result;
|
say to_json $result;
|
||||||
|
@ -6,19 +6,20 @@ use Path::Tiny;
|
|||||||
use File::Serialize;
|
use File::Serialize;
|
||||||
|
|
||||||
use Part1;
|
use Part1;
|
||||||
use Part2;
|
|
||||||
|
|
||||||
my $input = path('input')->slurp;
|
my $input = path('input')->slurp;
|
||||||
my $example = path('example')->slurp;
|
my $example = path('example')->slurp;
|
||||||
my %solutions = deserialize_file('solutions.yml')->%*;
|
my %solutions = deserialize_file('solutions.yml')->%*;
|
||||||
|
|
||||||
my $parsed = Part1::parse_input($example);
|
my $parsed = Part1::parse_input($example);
|
||||||
|
|
||||||
is $parsed->{directions} => [ 1, 0 ];
|
use DDP; p $parsed;
|
||||||
is $parsed->{nodes}{AAA} => [qw/ BBB CCC /];
|
|
||||||
|
|
||||||
is Part1::solution_1($example) => 2;
|
is $parsed->{directions} => [1,0];
|
||||||
is Part1::solution_1(<<'END') => 6;
|
is $parsed->{nodes}{AAA} => [ qw/ BBB CCC /];
|
||||||
|
|
||||||
|
is Part1::solution_1($example) => 2;
|
||||||
|
is Part1::solution_1(<<'END') => 6;
|
||||||
LLR
|
LLR
|
||||||
|
|
||||||
AAA = (BBB, BBB)
|
AAA = (BBB, BBB)
|
||||||
@ -26,10 +27,11 @@ BBB = (AAA, ZZZ)
|
|||||||
ZZZ = (ZZZ, ZZZ)
|
ZZZ = (ZZZ, ZZZ)
|
||||||
END
|
END
|
||||||
|
|
||||||
SKIP: {
|
SKIP: {
|
||||||
# skip "not there yet" if $solutions{1} eq 'TODO';
|
# skip "not there yet" if $solutions{1} eq 'TODO';
|
||||||
is Part1::solution_1($input) => $solutions{1};
|
is Part1::solution_1($input) => $solutions{1};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
@ -3,42 +3,11 @@ use 5.38.0;
|
|||||||
use Test2::V0;
|
use Test2::V0;
|
||||||
|
|
||||||
use Path::Tiny;
|
use Path::Tiny;
|
||||||
use File::Serialize;
|
|
||||||
|
|
||||||
use Part2;
|
use Part2;
|
||||||
|
|
||||||
my $input = path('input')->slurp;
|
my $input = path('input')->slurp;
|
||||||
my $example = <<END;
|
|
||||||
LR
|
|
||||||
|
|
||||||
11A = (11B, XXX)
|
is Part2::solution_2($input) => 'TODO';
|
||||||
11B = (XXX, 11Z)
|
|
||||||
11Z = (11B, XXX)
|
|
||||||
22A = (22B, XXX)
|
|
||||||
22B = (22C, 22C)
|
|
||||||
22C = (22Z, 22Z)
|
|
||||||
22Z = (22B, 22B)
|
|
||||||
XXX = (XXX, XXX)
|
|
||||||
END
|
|
||||||
my %solutions = deserialize_file('solutions.yml')->%*;
|
|
||||||
|
|
||||||
|
|
||||||
my $parsed = Part1::parse_input($example);
|
|
||||||
#is [Part2::get_cycle('11A',$parsed->{directions},$parsed->{nodes})] => [1,2];
|
|
||||||
##use DDP; my @x = Part2::get_cycle('22A',$parsed->{directions},$parsed->{nodes});p @x;
|
|
||||||
#is [Part2::get_cycle('22A',$parsed->{directions},$parsed->{nodes})] => [1,2,3];
|
|
||||||
|
|
||||||
|
|
||||||
#is Part2::solution_2($example) => 6;
|
|
||||||
|
|
||||||
$parsed = Part1::parse_input($input);
|
|
||||||
|
|
||||||
# my @initial = grep { /A$/ } keys $parsed->{nodes}->%*;
|
|
||||||
# for (@initial ) {
|
|
||||||
# say join " ", Part2::get_cycle($_,$parsed->{directions},$parsed->{nodes});
|
|
||||||
# }
|
|
||||||
|
|
||||||
|
|
||||||
is Part2::solution_2($input) => $solutions{2};
|
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
1: 19631
|
1: 19631
|
||||||
2: 21003205388413
|
2: TODO
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
use 5.38.0;
|
|
||||||
|
|
||||||
package Part1;
|
|
||||||
|
|
||||||
use List::AllUtils qw/ all sum /;
|
|
||||||
|
|
||||||
sub predict(@entries) {
|
|
||||||
my $sum = 0;
|
|
||||||
|
|
||||||
until( all { !$_ } @entries ) {
|
|
||||||
$sum += $entries[-1];
|
|
||||||
@entries = map { $entries[$_]-$entries[$_-1] } 1..$#entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub solution_1 ($input) {
|
|
||||||
my @lines = map { [split]} split "\n", $input;
|
|
||||||
|
|
||||||
return sum map { predict(@$_) } @lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -1,32 +0,0 @@
|
|||||||
use 5.38.0;
|
|
||||||
|
|
||||||
package Part2;
|
|
||||||
|
|
||||||
use Part1;
|
|
||||||
|
|
||||||
use List::AllUtils qw/ all sum /;
|
|
||||||
|
|
||||||
sub predict(@entries) {
|
|
||||||
my $sum = 0;
|
|
||||||
|
|
||||||
my @first = ();
|
|
||||||
|
|
||||||
until( all { !$_ } @entries ) {
|
|
||||||
push @first, $entries[0];
|
|
||||||
@entries = map { $entries[$_]-$entries[$_-1] } 1..$#entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(@first) {
|
|
||||||
$sum = pop( @first ) - $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub solution_2 ($input) {
|
|
||||||
my @lines = map { [split]} split "\n", $input;
|
|
||||||
|
|
||||||
return sum map { predict(@$_) } @lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -1,44 +0,0 @@
|
|||||||
use 5.38.0;
|
|
||||||
|
|
||||||
use Benchmark ':hireswallclock';
|
|
||||||
use Path::Tiny;
|
|
||||||
use JSON qw/ to_json /;
|
|
||||||
use DateTime;
|
|
||||||
use File::Serialize;
|
|
||||||
|
|
||||||
use Part1;
|
|
||||||
use Part2;
|
|
||||||
|
|
||||||
my $day = path('.')->absolute->basename =~ s/^0//r;
|
|
||||||
my $year = path('.')->absolute->parent->basename;
|
|
||||||
my $solutions = deserialize_file('solutions.yml');
|
|
||||||
|
|
||||||
my @parts = (
|
|
||||||
{ part => 1, sub => \&Part1::solution_1, expected => $solutions->{1} },
|
|
||||||
{ part => 2, sub => \&Part2::solution_2, expected => $solutions->{2} },
|
|
||||||
);
|
|
||||||
|
|
||||||
my $input = path('./input')->slurp;
|
|
||||||
|
|
||||||
for my $part (@parts) {
|
|
||||||
my $res = Benchmark::countit(
|
|
||||||
10,
|
|
||||||
sub {
|
|
||||||
$part->{sub}->($input) == $part->{expected} or die;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
my $result = {
|
|
||||||
day => $day,
|
|
||||||
year => $year,
|
|
||||||
|
|
||||||
#variant => '',
|
|
||||||
language => 'perl',
|
|
||||||
part => $part->{part},
|
|
||||||
time => $res->cpu_a / $res->iters,
|
|
||||||
persec =>$res->iters/$res->cpu_a ,
|
|
||||||
timestamp => DateTime->now->iso8601,
|
|
||||||
};
|
|
||||||
say to_json $result;
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
use 5.38.0;
|
|
||||||
|
|
||||||
use Test2::V0;
|
|
||||||
|
|
||||||
use Path::Tiny;
|
|
||||||
|
|
||||||
use Part1;
|
|
||||||
|
|
||||||
my $input = path('input')->slurp;
|
|
||||||
|
|
||||||
is Part1::predict(qw/0 3 6 9 12 15/) => 18;
|
|
||||||
is Part1::predict(qw/1 3 6 10 15 21/) => 28;
|
|
||||||
is Part1::predict(qw/10 13 16 21 30 45/) => 68;
|
|
||||||
|
|
||||||
is Part1::solution_1($input) => 1884768153;
|
|
||||||
|
|
||||||
done_testing;
|
|
@ -1,24 +0,0 @@
|
|||||||
use 5.38.0;
|
|
||||||
|
|
||||||
use Test2::V0;
|
|
||||||
|
|
||||||
use Path::Tiny;
|
|
||||||
|
|
||||||
use Part2;
|
|
||||||
|
|
||||||
my $input = path('input')->slurp;
|
|
||||||
|
|
||||||
is Part2::predict(qw/0 3 6 9 12 15/) => -3;
|
|
||||||
is Part2::predict(qw/1 3 6 10 15 21/) => 0;
|
|
||||||
is Part2::predict(qw/10 13 16 21 30 45/) => 5;
|
|
||||||
|
|
||||||
is Part2::solution_2(<<END) => 2;
|
|
||||||
0 3 6 9 12 15
|
|
||||||
1 3 6 10 15 21
|
|
||||||
10 13 16 21 30 45
|
|
||||||
END
|
|
||||||
|
|
||||||
isnt Part2::solution_2($input) => -59;
|
|
||||||
is Part2::solution_2($input) => 1031;
|
|
||||||
|
|
||||||
done_testing;
|
|
@ -1,2 +0,0 @@
|
|||||||
1: 1884768153
|
|
||||||
2: 1031
|
|
@ -16,8 +16,3 @@
|
|||||||
{"year":"2023","part":2,"language":"perl","day":"6","time":7.07875059716474e-06,"timestamp":"2023-12-06T15:43:13","persec":141267.867298578}
|
{"year":"2023","part":2,"language":"perl","day":"6","time":7.07875059716474e-06,"timestamp":"2023-12-06T15:43:13","persec":141267.867298578}
|
||||||
{"language":"perl","persec":85.2380952380952,"year":"2023","timestamp":"2023-12-07T16:08:30","time":0.011731843575419,"part":1,"day":"7"}
|
{"language":"perl","persec":85.2380952380952,"year":"2023","timestamp":"2023-12-07T16:08:30","time":0.011731843575419,"part":1,"day":"7"}
|
||||||
{"day":"7","part":2,"persec":85.2380952380952,"year":"2023","timestamp":"2023-12-07T16:08:43","time":0.011731843575419,"language":"perl"}
|
{"day":"7","part":2,"persec":85.2380952380952,"year":"2023","timestamp":"2023-12-07T16:08:43","time":0.011731843575419,"language":"perl"}
|
||||||
{"persec":113.488372093023,"timestamp":"2023-12-09T17:57:35","language":"perl","year":"2023","time":0.00881147540983607,"day":"9","part":1}
|
|
||||||
{"persec":109.783631232361,"timestamp":"2023-12-09T17:57:47","language":"perl","time":0.00910882604970008,"day":"9","part":2,"year":"2023"}
|
|
||||||
{"day":"8","persec":131.374407582938,"language":"perl","part":1,"time":0.00761183261183261,"timestamp":"2023-12-09T19:45:23","year":"2023"}
|
|
||||||
{"day":"8","language":"perl","time":0.0874789915966387,"year":"2023","timestamp":"2023-12-09T20:31:05","persec":11.431316042267,"part":2}
|
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
requires 'Math::Utils';
|
|
@ -9,8 +9,8 @@ use File::Serialize;
|
|||||||
use Part1;
|
use Part1;
|
||||||
use Part2;
|
use Part2;
|
||||||
|
|
||||||
my $day = path('.')->absolute->basename =~ s/^0//r;
|
my $day = path('.')->absolute->basename =~ s/^0//r;
|
||||||
my $year = path('.')->absolute->parent->basename;
|
my $year = path('.')->absolute->parent->basename;
|
||||||
my $solutions = deserialize_file('solutions.yml');
|
my $solutions = deserialize_file('solutions.yml');
|
||||||
|
|
||||||
my @parts = (
|
my @parts = (
|
||||||
@ -36,7 +36,6 @@ for my $part (@parts) {
|
|||||||
language => 'perl',
|
language => 'perl',
|
||||||
part => $part->{part},
|
part => $part->{part},
|
||||||
time => $res->cpu_a / $res->iters,
|
time => $res->cpu_a / $res->iters,
|
||||||
persec => $res->iters / $res->cpu_a,
|
|
||||||
timestamp => DateTime->now->iso8601,
|
timestamp => DateTime->now->iso8601,
|
||||||
};
|
};
|
||||||
say to_json $result;
|
say to_json $result;
|
||||||
|
Loading…
Reference in New Issue
Block a user