with Raku

This is my response to The Weekly Challenge #261.

You are given an array of integers,

Write a script to evaluate the absolute difference between element and digit sum of the given array.

Example 1:

`@ints`

.
Write a script to evaluate the absolute difference between element and digit sum of the given array.

Example 1:

Input: @ints = (1,2,3,45)
Output: 36
Element Sum: 1 + 2 + 3 + 45 = 51
Digit Sum: 1 + 2 + 3 + 4 + 5 = 15
Absolute Difference: | 51 - 15 | = 36

Example 2:
Input: @ints = (1,12,3)
Output: 9
Element Sum: 1 + 12 + 3 = 16
Digit Sum: 1 + 1 + 2 + 3 = 7
Absolute Difference: | 16 - 7 | = 9

Example 3:
Input: @ints = (1,2,3,4)
Output: 0
Element Sum: 1 + 2 + 3 + 4 = 10
Digit Sum: 1 + 2 + 3 + 4 = 10
Absolute Difference: | 10 - 10 | = 0

Example 4:
Input: @ints = (236, 416, 336, 350)
Output: 1296

Negative integers will cause problems. (How would *you*
handle e.g. «-25»? As «-2 + 5 = 3» or as «-(2 + 5) = -7»?) So I have
chosen to make them illegal. Zero is ok.

#! /usr/bin/env raku
unit sub MAIN (*@ints where all(@ints) ~~ UInt && @ints.elems > 0, # [1]
:v(:$verbose));
my $elem-sum = @ints.sum; # [2]
my $digit-sum = @ints>>.comb>>.sum.sum; # [3]
say ": Elem sum: $elem-sum, Digit sum: $digit-sum" if $verbose;
say abs($elem-sum - $digit-sum); # [4]

[1] Unsigned integers, and at least one of them.

See docs.raku.org/routine/sum for more information about `sum`

.

[3] Split each value into separate digits (with `>>.comb`

).
The result is a two dimentional list. Then we collapse all the inner lists
to a sum for each one (with `>>.sum`

). Then we collapse the remaining
list to a single sum (with `.sum`

).

See docs.raku.org/routine/comb for more information about `comb`

.

[4] Print the absolute value (`abs`

) of the difference
between the two values.

See docs.raku.org/routine/abs for more information about `abs`

.

Running it:

$ ./element-digit-sum 1 2 3 45
36
$ ./element-digit-sum 1 12 3
9
$ ./element-digit-sum 1 2 3 4
0
$ ./element-digit-sum 230 416 336 350
1296

Looking good.

With verbose mode:

$ ./element-digit-sum -v 1 2 3 45
: Elem sum: 51 Digit sum: 15
36
$ ./element-digit-sum -v 1 12 3
: Elem sum: 16, Digit sum: 7
9
$ ./element-digit-sum -v 1 2 3 4
: Elem sum: 10, Digit sum: 10
0
$ ./element-digit-sum -v 230 416 336 350
: Elem sum: 1332, Digit sum: 36
1296

You are given an array of integers,

Write a script to do the following:

In the end return the final value.

Example 1:

File: multiply-by-two
`@ints`

and an integer `$start`

.
Write a script to do the following:

- Look for $start in the array @ints, if found multiply the number by 2
- If not found stop the process otherwise repeat

In the end return the final value.

Example 1:

Input: @ints = (5,3,6,1,12) and $start = 3
Output: 24
Step 1: 3 is in the array so 3 x 2 = 6
Step 2: 6 is in the array so 6 x 2 = 12
Step 3: 12 is in the array so 12 x 2 = 24
24 is not found in the array so return 24.

Example 2:
Input: @ints = (1,2,4,3) and $start = 1
Output: 8
Step 1: 1 is in the array so 1 x 2 = 2
Step 2: 2 is in the array so 2 x 2 = 4
Step 3: 4 is in the array so 4 x 2 = 8
8 is not found in the array so return 8.

Example 3:
Input: @ints = (5,6,7) and $start = 2
Output: 2
2 is not found in the array so return 2.

#! /usr/bin/env raku
unit sub MAIN (Int $start is copy, # [1]
*@ints where all(@ints) ~~ Int && @ints.elems > 0, # [2]
:v(:$verbose));
my $step = 1; # [3]
while any(@ints) == $start # [4]
{
say ": Step { $step++ }: $start is in the array, so $start x 2 = \
{ $start * 2 }" if $verbose;
$start = $start * 2; # [5]
}
say ": $start is not found in the array, so return $start" if $verbose;
say $start; # [6]

[1] Specify the start (integer) value first. The
`is copy`

trait enables us to change the value later on (in [4]).

See docs.raku.org/type/Signature#index-entry-trait_is_copy for more information about `is copy`

.

[2] Follow on with the integer array, with at least one element.

[3] Used by verbose mode only.

[4] As long as the current value (called start for fun) is
present in the array, which we look up with an `any`

junction.

See docs.raku.org/routine/any for more information about `any`

.

[5] Update the start value.

[6] Print the result.

Running it:

$ ./multiply-by-two 3 5 3 6 1 12
24
$ ./multiply-by-two 1 1 2 4 3
8
$ ./multiply-by-two 2 5 6 7
2

Looking good.

With verbose mode:

$ ./multiply-by-two -v 3 5 3 6 1 12
: Step 1: 3 is in the array, so 3 x 2 = 6
: Step 2: 6 is in the array, so 6 x 2 = 12
: Step 3: 12 is in the array, so 12 x 2 = 24
: 24 is not found in the array, so return 24
24
$ ./multiply-by-two -v 1 1 2 4 3
: Step 1: 1 is in the array, so 1 x 2 = 2
: Step 2: 2 is in the array, so 2 x 2 = 4
: Step 3: 4 is in the array, so 4 x 2 = 8
: 8 is not found in the array, so return 8
8
$ ./multiply-by-two -v 2 5 6 7
: 2 is not found in the array, so return 2
2

And that's it.