This is my response to The Weekly Challenge #324.
$r
amd $c
.
$r
rows and $
columns using the given array.
Input: @ints = (1, 2, 3, 4), $r = 2, $c = 2
Output: ([1, 2], [3, 4])
Example 2:
Input: @ints = (1, 2, 3), $r = 1, $c = 3
Output: ([1, 2, 3])
Example 3:
Input: @ints = (1, 2, 3, 4), $r = 4, $c = 1
Output: ([1], [2], [3], [4])
File: 2d-array
#! /usr/bin/env raku
subset POSINT of Int where * > 0; # [1]
unit sub MAIN (POSINT :r(:$rows), # [1a]
POSINT :c(:$cols), # [1b]
*@ints where @ints.elems > 0 && all(@ints) ~~ Int, # [2]
:v(:$verbose));
die "Wrong nymber of elems" unless @ints.elems == $rows * $cols; # [3]
my @matrix; # [4]
while @ints.elems # [5]
{
my @row = @ints.splice(0,$cols)>>.Int; # [6]
say ": Row: { @row.join(",") }" if $verbose;
@matrix.push: @row; # [7]
}
say @matrix.raku; # [8]
[1] We define a custom type for positive integers with
subset
, then applying that to the two named arguments for rows [1a]
and columns [1b].
See docs.raku.org/routine/subset for more information about subset
.
[2] A slurpy array of integers, with at least one element.
[3] Ensure that we have the correct number of elements to fill the matrix.
[4] The matrix, the two dimentional array, will end up here.
[5] As long as we have values to twodimentionalise.
[6] Use splice
to remove $cols
number of elements
from the beginning of the array. The trailing >>.Int
is there to get
rid of the IntStr
type, which does not look nice when we print them.
See docs.raku.org/routine/splice for more information about splice
.
[7] Push that subarray to the result. This gives one new element to the result; the very same subarray.
[8] Print the result, using the built in raku
method.
See docs.raku.org/routine/raku for more information about raku
.
Running it:
$ ./2d-array -r=2 -c=2 1 2 3 4
[[1, 2], [3, 4]]
$ ./2d-array -r=1 -c=3 1 2 3
[[1, 2, 3],]
$ ./2d-array -r=4 -c=1 1 2 3 4
[[1], [2], [3], [4]]
Looking good.
With verbose mode:
$ ./2d-array -v -r=2 -c=2 1 2 3 4
: Row: 1,2
: Row: 3,4
[[1, 2], [3, 4]]
$ ./2d-array -v -r=1 -c=3 1 2 3
: Row: 1,2,3
[[1, 2, 3],]
$ ./2d-array -v -r=4 -c=1 1 2 3 4
: Row: 1
: Row: 2
: Row: 3
: Row: 4
[[1], [2], [3], [4]]
Input: @ints = (1, 3)
Output: 6
Subset [1], total XOR = 1
Subset [3], total XOR = 3
Subset [1, 3], total XOR => 1 XOR 3 => 2
Sum of total XOR => 1 + 3 + 2 => 6
Example 2:
Input: @ints = (5, 1, 6)
Output: 28
Subset [5], total XOR = 5
Subset [1], total XOR = 1
Subset [6], total XOR = 6
Subset [5, 1], total XOR => 5 XOR 1 => 4
Subset [5, 6], total XOR => 5 XOR 6 => 3
Subset [1, 6], total XOR => 1 XOR 6 => 7
Subset [5, 1, 6], total XOR => 5 XOR 1 XOR 6 => 2
Sum of total XOR => 5 + 1 + 6 + 4 + 3 + 7 + 2 => 28
Example 3:
Input: @ints = (3, 4, 5, 6, 7, 8)
Output: 480
First a version that does not work out, courtesy of haste when reading the challenge...
File: total-xor-wrong
#! /usr/bin/env raku
unit sub MAIN (*@ints where @ints.elems > 0 && all(@ints) ~~ UInt, # [1]
:v(:$verbose));
my $total = 0; # [2]
for 0 .. @ints.end -> $i # [3]
{
for $i .. @ints.end -> $j # [4]
{
my $xor = [+^] @ints[$i .. $j]; # [5]
$total += $xor; # [6]
say "$i .. $j -> [{ @ints[$i .. $j].join(",") }] -> $xor" if $verbose;
}
}
say $total; # [7]
[1] A slurpy array (with at least one element) of unsigned
ints, courtesy of the UInt
type.
See docs.raku.org/type/UInt for more information about the UInt
type.
[2] The grand total will end up here.
[3] Iterate over the starting index,
[4] and the ending index.
[5]
Apply the Bitwise XOR Operator +^
on the entire subarray with the Reduction Metaoperator []
.
See
docs.raku.org/routine/+$CIRCUMFLEX_ACCENT
for more information about the infix bitwise XOR (exclusive or) operator +^
.
See
docs.raku.org/language/operators#Reduction_metaoperators for more
information about the Reduction Metaoperator []
.
[6] Add the result for the current subarray to the grand total.
[7] Print the result.
It does not work out, as shjown for the second example:
$ ./total-xor-wrong -v 5 1 6
0 .. 0 -> [5] -> 5
0 .. 1 -> [5,1] -> 4
0 .. 2 -> [5,1,6] -> 2
1 .. 1 -> [1] -> 1
1 .. 2 -> [1,6] -> 7
2 .. 2 -> [6] -> 6
25
The problem is that I went for subarray instead of subset. That is actually easy to fix, leading to a shorter program:
File: total-xor
#! /usr/bin/env raku
unit sub MAIN (*@ints where @ints.elems > 0 && all(@ints) ~~ UInt,
:v(:$verbose));
my $total = 0;
for @ints.combinations(1..Inf) -> @comb # [1]
{
my $xor = [+^] @comb; # [2]
$total += $xor;
say ": [{ @comb.join(",") }] -> $xor" if $verbose;
}
say $total;
[1] Iterate over all the combinations
for the array, excluding the empty one (size 0).
See docs.raku.org/routine/combinations for more information about combinations
.
[2] Apply the Bitwise XOR Operator +^
on each combination.
Running it:
$ ./total-xor -1 3
6
$ ./total-xor -5 1 6
28
$ ./total-xor -3 4 5 6 7 8
480
Looking good.
With verbose mode:
$ ./total-xor -v 1 3
: [1] -> 1
: [3] -> 3
: [1,3] -> 2
6
$ ./total-xor -v 5 1 6
: [5] -> 5
: [1] -> 1
: [6] -> 6
: [5,1] -> 4
: [5,6] -> 3
: [1,6] -> 7
: [5,1,6] -> 2
28
$ ./total-xor -v 3 4 5 6 7 8
: [3] -> 3
: [4] -> 4
: [5] -> 5
: [6] -> 6
: [7] -> 7
: [8] -> 8
: [3,4] -> 7
: [3,5] -> 6
: [3,6] -> 5
: [3,7] -> 4
: [3,8] -> 11
: [4,5] -> 1
: [4,6] -> 2
: [4,7] -> 3
: [4,8] -> 12
: [5,6] -> 3
: [5,7] -> 2
: [5,8] -> 13
: [6,7] -> 1
: [6,8] -> 14
: [7,8] -> 15
: [3,4,5] -> 2
: [3,4,6] -> 1
: [3,4,7] -> 0
: [3,4,8] -> 15
: [3,5,6] -> 0
: [3,5,7] -> 1
: [3,5,8] -> 14
: [3,6,7] -> 2
: [3,6,8] -> 13
: [3,7,8] -> 12
: [4,5,6] -> 7
: [4,5,7] -> 6
: [4,5,8] -> 9
: [4,6,7] -> 5
: [4,6,8] -> 10
: [4,7,8] -> 11
: [5,6,7] -> 4
: [5,6,8] -> 11
: [5,7,8] -> 10
: [6,7,8] -> 9
: [3,4,5,6] -> 4
: [3,4,5,7] -> 5
: [3,4,5,8] -> 10
: [3,4,6,7] -> 6
: [3,4,6,8] -> 9
: [3,4,7,8] -> 8
: [3,5,6,7] -> 7
: [3,5,6,8] -> 8
: [3,5,7,8] -> 9
: [3,6,7,8] -> 10
: [4,5,6,7] -> 0
: [4,5,6,8] -> 15
: [4,5,7,8] -> 14
: [4,6,7,8] -> 13
: [5,6,7,8] -> 12
: [3,4,5,6,7] -> 3
: [3,4,5,6,8] -> 12
: [3,4,5,7,8] -> 13
: [3,4,6,7,8] -> 14
: [3,5,6,7,8] -> 15
: [4,5,6,7,8] -> 8
: [3,4,5,6,7,8] -> 11
480
And that's it.