# Perl Weekly Challenge 122: mangling numbers

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 122.

## PWC 122 - Task 1

The first task was about computing the average of a stream of numbers. Since it is not clear to me if the word stream here means a continuos input from the user, I provided two different `MAIN`s: one that gets an array of numbers, and one that reads from `STDIN`.
The application is as follows:

``````multi sub MAIN( *@N where { @N.elems == @N.grep( * ~~ Int ).elems }) {
my @average;
@average.push: (@N[ 0 .. @average.elems - 1 ].sum + \$_) / ( @average.elems + 1 ) for @N;

@average.say;
}

multi sub MAIN() {
"Insert a number at time".say;

my @average;
my \$sum = 0;
for lines() {
"Not a number".say && next if \$_ !~~ / \d+ /;
\$sum += \$_;
@average.push: \$sum / ( @average.elems + 1 );
"Average trend so far: { @average.say }";

}
}
``````

The streaming `MAIN` (the second one) is a little boring: it accumulates the sum of provided numbers into a `\$sum` variable, and pushes the computed average into an `@average` array. I don’t keep track of how many numbers have been provided, since `@average` contains that information too. Also, I do test for good numbers before computing any value.
The first `MAIN` does pretty much the same, but the `@average` array is populated within a `for` loop that scans every input number, and the average value is made by summing the current value with the slice of previous values on the input `@N` array.

## PWC 122 - Task 2

The second task was about finding out all possible sequences of available baseball scores that provide a final score specified as input.
I decided to let Raku do a lot of computations, producing all available permutations of numbers and throwing away those that do not provide the right final score. I could not come up with a simpler solution, from the point of view of code, than this, but clearly it is strongly de-optimized!

``````sub MAIN( Int \$S ) {
my @available-points = 1, 2, 3;
my \$begin = ( @available-points[ 0 ] x \$S ).Int;
my \$end   = ( @available-points[ * - 1 ] x \$S ).Int;
my @scores;

for ( \$begin .. \$end ) {
my @digits = \$_.split( '', :skip-empty ).grep( * == any( @available-points ) );
next if ! @digits.grep: \$_ for @available-points;
next if @digits.sum != \$S;
my \$score =  @digits.grep( * == any( @available-points ) ).join;;
@scores.push: \$score if ( ! @scores.grep( \$score ) );

}

@scores.join( "\n" ).say;
}
``````

The idea is that, assuming the final score `\$S` as `4`, I got all values between `1111` and `3333`. After that I check if the number, split into its `@digits` can give me a sum up to `\$S`, and in the case I place it into the `@scores` array, after trimming out all zeros. If the number includes digits that are not within the `@available-points` or if the sum of those digits is not the one I’m looki9ng for, I discard the number.
Trimming out the `0` from a number means that the `@scores` array is going to include duplicates (e.g., `1002` and `1200` will both result in `12`), so at the end I apply `unique` to get a single value out of all duplicates.

The article Perl Weekly Challenge 122: mangling numbers has been posted by Luca Ferrari on July 20, 2021