This is my response to The Weekly Challenge #261.
@ints
.
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.
File: element-digit-sum
#! /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
@ints
and an integer $start
.
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.