# Perl Weekly Challenge 106: quick and easy!

One way to let me improve my knowledge about Raku (aka Perl 6) is to implement programs in it. Unluckily, I don’t have any production code to implement in Raku yet (sob!). So, why not try solving the Perl Weekly Challenge tasks?

In the following, the assigned tasks for Challenge 106.

## PWC 106 - Task 1

The first task was quite easy, even if I did not found a solution more comfortable than iterating on a `for` loop. The idea was to sort an array of integers, and get the difference between sequentially adiacent numbers.

### The Raku-ish solution

Thanks to some help, I got to know that `.rotor` can have a step argument that can instrument the system to go back, therefore the shortest solution I can come up is:

``````sub MAIN( *@N where { @N.elems == @N.grep( * ~~ Int ).elems } ) {
@N.sort.rotor( 2 => -1 ).map( { \$_[ 1 ] - \$_[ 0 ] } ).max.say;
}
``````

• sort the `@N` array;
• extract batchs of `2` elements, and on each batch go back of one position (i.e., `-1`);
• `map` the resulting sub-array to its difference;
• compute the `max` of the resulting array;
• print it out with `say`.
Nice!

Without the trick about `rotor`, the other ways to solve the problem did involved looping on the array. That is:

``````sub MAIN( *@N where { @N.elems == @N.grep( * ~~ Int ).elems } ) {
my @M = 0;
my @n = @N.sort;
@M.push: @n[ \$_ + 1 ] - @n[ \$_ ]  for 0 ..^ @n.elems - 1;
say @M.max;
}
``````

The idea is:
• sort the array into `@n`;
• iterate on the sorted array and then compute the difference between a couple of elements, this does not require any absolute value since the array is sorted;
• push the result into the `@M` array;
• print out the `max` value of the `@M` array.

This solution works fine, but it does consume memory to store all intermediate results, and of course there is the possibility to use a single scalar value instead of the `@M` array:

`````` my \$max = 0;
\$max = @n[ \$_ + 1 ] - @n[ \$_ ] > \$max
?? @n[ \$_ + 1 ] - @n[ \$_ ]
!! \$max  for 0 ..^ @n.elems - 1;
say \$max;
``````

The trick is the same, but this time `\$max` stores only the difference when it is greater than the previously computed difference.

## PWC 106 - Task 2

The second task was easy too, because Raku already provides the very same example in the documentation. The task was about printing out a decimal number coming from a rational one with the periodic part in parenthesis.
This is simple enough because `Rat` provides the `base-repeat` method that gives an array where the result is split into the non-repeating part and the repeating one. The task therefore is:

``````sub MAIN( Int \$D, Int \$N where { \$N != 0 } ) {
my @values = ( \$D / \$N ).base-repeating( 10 );

print @values[ 0 ];
print '(%s)'.sprintf: @values[ 1 ] if ( @values[ 1 ] );
put '';
}
``````

As you can see, there is much more code involved in the printing phase that in the computing one.
To shorten the printing phase, it is possible to do something like the following:

``````sub MAIN( Int \$D, Int \$N where { \$N != 0 } ) {
my @values = ( \$D / \$N ).base-repeating( 10 );

@values[ 0 ].say and exit if ( ! @values[  1 ] );
'%s(%s)'.sprintf( @values ).say;
}
``````

Therefore, the `printf` approach is used only if there is the repeting part, otherwise a simple `say` is used and the program is terminated. Please note the usage of low priority `and` before the `exit`, otherwise the program will terminate without printing anything.

The article Perl Weekly Challenge 106: quick and easy! has been posted by Luca Ferrari on March 29, 2021