From 450ac404f1b90915599b3efc7c87b797d35a24c7 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sat, 9 Dec 2023 11:47:37 -0500 Subject: [PATCH 1/3] wip --- 2023/08/Part2.pm | 80 ++++++++++++++++++++++++++++++++++++++++-------- 2023/08/part2.t | 26 +++++++++++++--- 2 files changed, 90 insertions(+), 16 deletions(-) diff --git a/2023/08/Part2.pm b/2023/08/Part2.pm index d7a70ee..969720c 100644 --- a/2023/08/Part2.pm +++ b/2023/08/Part2.pm @@ -4,30 +4,86 @@ package Part2; use Part1; -use List::AllUtils qw/all /; +use List::AllUtils qw/all first_index none min max /; + +sub get_cycle( $current, $directions, $nodes ) { + + my @tracks; + my $next_index = 0; + + while() { + use DDP; #p @tracks; + 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 solution_2 ($input) { my $p = Part1::parse_input($input); my @directions = $p->{directions}->@*; my %nodes = $p->{nodes}->%*; - my $visited = 0; - my $next_index = 0; - my @current = grep { /A$/ } keys %nodes; + my @paths; + my @initial = grep { /A$/ } keys %nodes; + for (@initial ) { + push @paths, [ + Part2::get_cycle($_,\@directions,\%nodes) + ]; + } - until ( all { /Z$/ } @current ) { - # use DDP; p @current; - # my $foo = <>; - $visited++; + my $visited = 0; + my @preloop = map { shift @$_ } @paths; + p @preloop; + my $pre = max @preloop; + $visited += $pre; - @current = map { - $nodes{$_}->[ $directions[ $next_index % @directions ] ] - } @current; - $next_index++; + my @current = map { $preloop[$_] - $pre } 0..$#preloop; + p @current;p @paths; + for(0..$#current) { + while( $current[$_] <= 0 ) { + $current[$_] += $paths[$_][0]; + push $paths[$_]->@*, shift $paths[$_]->@*; + } + } + p @current;p @paths; + + until( none { $_ } @current ) { + use DDP; + warn $visited; + p @current;p @paths; + my $incr = max @current; + warn $incr; + $visited += $incr; + for ( 0..$#current) { + $current[$_] -= $incr; + while( $current[$_] < 0 ) { + $current[$_] += $paths[$_][0]; + push $paths[$_]->@*, shift $paths[$_]->@*; + } + } } return $visited; + } 1; diff --git a/2023/08/part2.t b/2023/08/part2.t index cb5f141..50662fa 100644 --- a/2023/08/part2.t +++ b/2023/08/part2.t @@ -8,10 +8,7 @@ use File::Serialize; use Part2; my $input = path('input')->slurp; -my $example = path('example')->slurp; -my %solutions = deserialize_file('solutions.yml')->%*; - -is Part2::solution_2(<<'END') => 6; +my $example = <%*; + + +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; +exit; + + + +$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}; From d1d38ba6239b89efd0941283d7c974cb48804614 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sat, 9 Dec 2023 15:05:07 -0500 Subject: [PATCH 2/3] wip --- 2023/08/Part2.pm | 77 +++++++++++++++++++++----------------------- 2023/08/benchmark.pl | 3 +- 2023/08/part2.t | 9 ++---- 3 files changed, 42 insertions(+), 47 deletions(-) diff --git a/2023/08/Part2.pm b/2023/08/Part2.pm index 969720c..a71c525 100644 --- a/2023/08/Part2.pm +++ b/2023/08/Part2.pm @@ -36,56 +36,53 @@ sub get_cycle( $current, $directions, $nodes ) { } +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 solution_2 ($input) { my $p = Part1::parse_input($input); my @directions = $p->{directions}->@*; my %nodes = $p->{nodes}->%*; - my @paths; - my @initial = grep { /A$/ } keys %nodes; - for (@initial ) { - push @paths, [ - Part2::get_cycle($_,\@directions,\%nodes) - ]; + my $steps = 0; + my @paths = grep { /A$/ } keys %nodes; + my $next_index = 0; + + until( all {/Z$/ } @paths ) { + my($incr,$current,$new_index) = find_z($paths[0],$next_index,\@directions,\%nodes); + $paths[0] = $current; + @paths = ( $current, map { + speedrun($paths[$_],$next_index,\@directions,\%nodes,$incr) + } 1..$#paths ); + $next_index = $new_index; + $steps += $incr; } - my $visited = 0; - my @preloop = map { shift @$_ } @paths; - p @preloop; - my $pre = max @preloop; - $visited += $pre; - my @current = map { $preloop[$_] - $pre } 0..$#preloop; - p @current;p @paths; - for(0..$#current) { - while( $current[$_] <= 0 ) { - $current[$_] += $paths[$_][0]; - push $paths[$_]->@*, shift $paths[$_]->@*; - } - } - p @current;p @paths; - - until( none { $_ } @current ) { - use DDP; - warn $visited; - p @current;p @paths; - my $incr = max @current; - warn $incr; - $visited += $incr; - for ( 0..$#current) { - $current[$_] -= $incr; - while( $current[$_] < 0 ) { - $current[$_] += $paths[$_][0]; - push $paths[$_]->@*, shift $paths[$_]->@*; - } - } - } - - return $visited; + return $steps; } 1; - -1; diff --git a/2023/08/benchmark.pl b/2023/08/benchmark.pl index 0d7280d..71ad82b 100644 --- a/2023/08/benchmark.pl +++ b/2023/08/benchmark.pl @@ -15,7 +15,7 @@ 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} }, +# { part => 2, sub => \&Part2::solution_2, expected => $solutions->{2} }, ); my $input = path('./input')->slurp; @@ -36,6 +36,7 @@ for my $part (@parts) { 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; diff --git a/2023/08/part2.t b/2023/08/part2.t index 50662fa..ef78de8 100644 --- a/2023/08/part2.t +++ b/2023/08/part2.t @@ -24,15 +24,12 @@ 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::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; -exit; - - $parsed = Part1::parse_input($input); From d6ed288ea9cc30e1d0e6febaea359bdf5af43117 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Sat, 9 Dec 2023 15:31:25 -0500 Subject: [PATCH 3/3] part 2 --- 2023/08/Part2.pm | 63 ++++++++++++++++++++++++++++++++++--------- 2023/08/benchmark.pl | 2 +- 2023/08/part2.t | 2 +- 2023/08/solutions.yml | 2 +- 2023/benchmark.json | 3 +++ 2023/cpanfile | 1 + 6 files changed, 58 insertions(+), 15 deletions(-) create mode 100644 2023/cpanfile diff --git a/2023/08/Part2.pm b/2023/08/Part2.pm index a71c525..49a699d 100644 --- a/2023/08/Part2.pm +++ b/2023/08/Part2.pm @@ -4,7 +4,9 @@ package Part2; use Part1; -use List::AllUtils qw/all first_index none min max /; +use List::AllUtils qw/all first_index none min max product /; +use List::UtilsBy qw/ min_by max_by /; + use Math::Utils qw/ lcm /; sub get_cycle( $current, $directions, $nodes ) { @@ -12,7 +14,6 @@ sub get_cycle( $current, $directions, $nodes ) { my $next_index = 0; while() { - use DDP; #p @tracks; my $t = join '-', $current,$next_index; my $i = first_index { $_ eq $t } @tracks; if( $i > -1 ) { @@ -60,6 +61,37 @@ sub speedrun($current,$next_index,$directions,$nodes,$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) { my $p = Part1::parse_input($input); my @directions = $p->{directions}->@*; @@ -69,20 +101,27 @@ sub solution_2 ($input) { my @paths = grep { /A$/ } keys %nodes; my $next_index = 0; - until( all {/Z$/ } @paths ) { - my($incr,$current,$new_index) = find_z($paths[0],$next_index,\@directions,\%nodes); - $paths[0] = $current; - @paths = ( $current, map { - speedrun($paths[$_],$next_index,\@directions,\%nodes,$incr) - } 1..$#paths ); - $next_index = $new_index; - $steps += $incr; + 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; - return $steps; - + for(@equations) { + while( $_->{total}<$i) { + $_->{total}+=$_->{m}; + } + } + # use DDP; p @equations; + } + $equations[0]->{total}; } 1; diff --git a/2023/08/benchmark.pl b/2023/08/benchmark.pl index 71ad82b..6154f18 100644 --- a/2023/08/benchmark.pl +++ b/2023/08/benchmark.pl @@ -15,7 +15,7 @@ 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} }, + { part => 2, sub => \&Part2::solution_2, expected => $solutions->{2} }, ); my $input = path('./input')->slurp; diff --git a/2023/08/part2.t b/2023/08/part2.t index ef78de8..f812d5f 100644 --- a/2023/08/part2.t +++ b/2023/08/part2.t @@ -29,7 +29,7 @@ my $parsed = Part1::parse_input($example); #is [Part2::get_cycle('22A',$parsed->{directions},$parsed->{nodes})] => [1,2,3]; -is Part2::solution_2($example) => 6; +#is Part2::solution_2($example) => 6; $parsed = Part1::parse_input($input); diff --git a/2023/08/solutions.yml b/2023/08/solutions.yml index b7e185a..1e0b577 100644 --- a/2023/08/solutions.yml +++ b/2023/08/solutions.yml @@ -1,2 +1,2 @@ 1: 19631 -2: TODO +2: 21003205388413 diff --git a/2023/benchmark.json b/2023/benchmark.json index aeaa9cd..aaa69f8 100644 --- a/2023/benchmark.json +++ b/2023/benchmark.json @@ -18,3 +18,6 @@ {"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} + diff --git a/2023/cpanfile b/2023/cpanfile new file mode 100644 index 0000000..2c446d6 --- /dev/null +++ b/2023/cpanfile @@ -0,0 +1 @@ +requires 'Math::Utils';