Advent Calendar - December 9, 2022

Friday, Dec 9, 2022| Tags: Raku

Advent Calendar 2022

|   Day 8   |   Day 9   |   Day 10   |


The gift is presented by Luca Ferrari. Today he is talking about his solution to “The Weekly Challenge - 155”. This is re-produced for Advent Calendar 2022 from the original post by him.



It is sad that, after more than two years of me doing Raku, I still don’t have any production code project to work on. Therefore, in order to keep my coding and Raku-ing (is that a term?) knowdledge, I try to solve every Perl Weekly Challenge tasks.

PWC 155 - Task 1


Not so hard: compute the Fortunate numbers, those numbers that sum with a pn give a prime number. Here, pn stands for the multiplication of all n prime numbers. The task added to find out all first 8 unique Fortunate numbers.


sub MAIN( Int $limit where { $limit > 0 } = 8 ) {
    my @fortunate-numbers = lazy gather {
        for 2 .. Inf {
            my @pn = ( 1 .. $_ ).grep: *.is-prime;
            next if ! @pn;
            for @pn.max + 1 .. Inf -> $m {
                take $m and last if ( ( [*] @pn ) + $m ).is-prime;
            }
        }
    }

    my @unique-fortunate-numbers;
    my $last-number = 0;
    while ( @unique-fortunate-numbers.elems < $limit ) {
        my $fortunate = @fortunate-numbers[ $last-number++ ];
        @unique-fortunate-numbers.push: $fortunate if ! @unique-fortunate-numbers.grep: * ~~ $fortunate;
    }

    @unique-fortunate-numbers[ 0 .. $limit - 1 ].sort.join( "\n" ).say;
}

The @fortunate-numbers is a lazy array computed by means of @pn, which is the list of all prime numbers up to a given number, and then a new loop is done to find out the smallest $m number greater than any value in @pn that, when summed with the multiplication of all values in @pn gives a prime.

To find out only unique numbers, I loop again to build a @unique-fortunate-numbers array and stop the searching for as soon as the elements in the array are at the limit.


PWC 155 - Task 2


Pisano Period: finding out the repetition of the sequence of Fibonacci when every element is modulo a given number.


sub MAIN( Int $nth where { $nth >= 3 } = 3,
          Int $accuracy where { $accuracy > 1 } = 5,
          Bool :$verbose = False ) {

    my @fibonacci = 0, 1, 1, 2, * + * ... *;
    my @pisano    = @fibonacci.map: * % 3;

    # with nth >= 3 the period is always even
    my $period = 2;

    # build $accuracy arrays to check
    my @checking.push: @pisano[ ( 0 + $period * $_ ) .. ( $period * ( $_  + 1 ) ) - 1 ] for 1 .. $accuracy;

    # while the array are not all the same, grow them and recheck
    while ( not [eqv] @checking ) {
        $period += 2;
        @checking = ();
        @checking.push: @pisano[ ( 0 + $period * $_ ) .. ( $period * ( $_  + 1 ) ) - 1 ] for 1 .. $accuracy;
    }

    @checking.join( "\n" ).join( ',' ).say if $verbose;
    "Pisano period $nth is $period".say;

}

The idea is to build a lazy sequence @pisano that maps every element of the Fibonacci’s serie modulo 3 as asked. Since, when the modulo applied is greater or equal to 3, the period (i.e., the size of repeating part of the sequence) is always even, I start with a $period of 2. Then I extract a number of arrays of size $period equal in number to $accuracy, e.g., 5 arrays of size 2. Last, I check if the extracted array are all the same, i.e., are eqv. If they are, the $period is found, otherwise I increase the period of a even value and do it again.



If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.

|   Advent Calendar 2022   |

SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.

Contact with me