Exclusive or 2D
with Raku

by Arne Sommer

Exclusive or 2D with Raku

[346] Published 8. June 2025.

This is my response to The Weekly Challenge #324.

Challenge #324.1: 2D Array

You are given an array of integers and two integers $r amd $c.

Write a script to create two dimension array having $r rows and $ columns using the given array.

Example 1:
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]]

Challenge #324.2: Total XOR

You are given an array of integers.

Write a script to return the sum of total XOR for every subset of given array.

Example 1:
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.