Perl Weekly Challenge 150: Fibonacci and squares (again!)
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.In the following, the assigned tasks for Challenge 150.
And this week, as for the previous PWC, I had time to quickly implement the tasks also on PostgreSQL
plpgsql language:
PWC 150 - Task 1
This task was about producing a sequence of Fibonacci’s words, that is given two initial words (made by digits), concatente them as in a Fibonacci sequence. Moreover, print the51th digits of the word with 51 characters and exit.
sub MAIN( Str $a, Str $b where { $a.chars == $b.chars
                                 && $a ~~ / ^ <[0 .. 9]>+ $ /
                                 && $b ~~ / ^ <[0 .. 9]>+ $ / } ) {
    my @fibonacci-words = $a, $b;
    for 0 .. Inf {
        @fibonacci-words.push: @fibonacci-words[ * - 2 ] ~ @fibonacci-words[ * - 1 ];
        @fibonacci-words[ * - 1 ].substr( @fibonacci-words[ * - 1 ].chars - 2, 1 ).say and last if @fibonacci-words[ * - 1 ].chars - 1 == 51;
    }
    @fibonacci-words.join( "\n" ).say;
}
The idea is simple: I loop forever concatenating at each step the previous string with the previous-previous one. Then, if the current string, that is the last one in the
@fibonacci-words array is of the right length, I print the required char. Please note that there is the need to consider that 51 is not a valid number of char, rathern it should be 52 as chars and string length are not the same.
PWC 150 - Task 2
The second task was harder: find out all the numbers that are freesquare integers. A freesquare integer is an integer that has no repeating prime factor.sub factors ( Int $number ) {
    return $number if $number == 1 || $number.is-prime;
    my @factors;
    my $value = $number;
    for ( 2 .. $value div 2 ).grep( *.is-prime ) -> $candidate {
        while $value %% $candidate {
            @factors.push: $candidate;
            $value /= $candidate;
        }
    }
    return @factors;
}
sub MAIN( Int $limit = 500 ) {
    my %solutions;
    for 1 .. $limit {
        my @factors = factors( $_ );
        my $ok = True;
        for @factors -> $current-factor {
            if @factors.grep( $current-factor ).elems > 1 {
                $ok = False;
                last;
            }
        }
        %solutions{ $_ } = @factors if $ok;
    }
    "$_ = { %solutions{$_}.join( ' x ' ); }".say for %solutions.keys.sort;
}
The
factors routine is a classical routine that returns the prime factors of a given number.
In the MAIN I do iterate up to the specified $limit, and for every value I extract the @factors list. Then I iterate on each number of the list to catch if it repeats more than one time, and in such case I discard the value and start over with a new value. If the number, on the other hand, has non repeating factors, I place it into an hash %solutions aside its factors, so that I can print out every detail.