Divisible Difference
with Raku

by Arne Sommer

Divisible Difference with Raku

[423] Published 8. November 2026.

This is my response to The Weekly Challenge #398.

#398.1 Divisible Average You are given an array of positive integers.

Write a script to return the closest integer to the mean value of all even integers that are divisible by 3. If none is divisible, return 0.

Example 1:
Input: @arr = (18, 5, 7, 11)
Output: 18

18 is the only even number and divisible by 3.
Average: 18 / 1 = 18.
Example 2:
Input: @arr = (6, 12, 18, 24, 30, 40)
Output: 18

The qualifying numbers are 6, 12, 18, 24, and 30.
Average: (6 + 12 + 18 + 24 + 30) / 5 = 90 / 5 = 18
Example 3:
Input: @arr = (3, 9, 15, 21, 27)
Output: 0

None of the elements are even.
Since no elements qualify, return 0.
Example 4:
Input: @arr = (6, 12, 14, 20)
Output: 9

The qualifying numbers are 6 and 12.
Average: (6 + 12) / 2 = 9.
Example 5:
Input: @arr = (6, 6, 6, 12, 12)
Output: 8

All five numbers are even and divisible by 3.
Average: (6 + 6 + 6 + 12 + 12) / 5 = 8.4 => 8

This task is a cousin of «Absent Smallest Positive», the first part of last week's challenge. See Absent Reflection with Raku. Both programs are built around the mean of the array's elements. Last week, the mean of all elements served as a lower bound for the search for an absent positive integer; this time the array is first filtered to the even numbers divisible by 3, and the mean of the survivors is rounded to the closest integer.

File: divisible-average
#! /usr/bin/env raku

unit sub MAIN (*@arr where @arr.elems > 0 && all(@arr) ~~ Int,
               :v(:$verbose));

my @qualifying = @arr.grep: * %% 6;

if $verbose
{
  for @arr -> $n
  {
    say ": $n " ~ (
        $n %% 6
            ?? "is even and divisible by 3"
            !! $n % 2
            ?? "is not even"
            !! "is not divisible by 3"
    );
  }
  say ": average is {@qualifying.sum / @qualifying.elems}"
    if @qualifying;
}

say @qualifying.elems
    ?? (@qualifying.sum / @qualifying.elems).round
    !! 0;

[3] Integers only, and we require at least one value.

[6] Get the qualifying values; integers divisible by 3. We use divisible by 6, as the result must be an integer - i.e. beeing divisible by two. Combining them is neat.

[23] Do we actually have any qualifying elements?

[24] If so, get the average value (the sum divided by the count) and round it (with round).

See docs.raku.org/routine/round for more information about round.

[25] If not, print zero.

Running it:

$ ./divisible-average 18 5 7 11
18

$ ./divisible-average 6 12 18 24 30 40
18

$ ./divisible-average 3 9 15 21 27
0

$ ./divisible-average 6 12 14 20
9

$ ./divisible-average 6 6 6 12 12
8

Looking good.

With verbose mode:

$ ./divisible-average -v 18 5 7 11
: 18 is even and divisible by 3
: 5 is not even
: 7 is not even
: 11 is not even
: average is 18
18

$ ./divisible-average -v 6 12 18 24 30 40
: 6 is even and divisible by 3
: 12 is even and divisible by 3
: 18 is even and divisible by 3
: 24 is even and divisible by 3
: 30 is even and divisible by 3
: 40 is not divisible by 3
: average is 18
18

$ ./divisible-average -v 3 9 15 21 27
: 3 is not even
: 9 is not even
: 15 is not even
: 21 is not even
: 27 is not even
0

$ ./divisible-average -v 6 12 14 20
: 6 is even and divisible by 3
: 12 is even and divisible by 3
: 14 is not divisible by 3
: 20 is not divisible by 3
: average is 9
9

$ ./divisible-average -v 6 6 6 12 12
: 6 is even and divisible by 3
: 6 is even and divisible by 3
: 6 is even and divisible by 3
: 12 is even and divisible by 3
: 12 is even and divisible by 3
: average is 8.4
8

#398.2 String Difference You are given an array of equal length strings.

Write a script to find the difference integer array of each word in the given array. There will be one word with a different array; return that word.

Each words[i] can be converted into a difference integer array difference[i] of length n - 1 where difference[i][j] = words[i][j+1] - words[i][j]

Example 1:
Input: @words = ("ab", "bc", "cd", "zy")
Output: "zy"

"ab" => [1 - 0] = [1]
"bc" => [2 - 1] = [1]
"cd" => [3 - 2] = [1]
"zy" => [24 - 25] = [-1]
Example 2:
Input: @words = ("cba", "fed", "azy")
Output: "azy"

"cba" => [1 - 2, 0 - 1] = [-1, -1]
"fed" => [4 - 5, 3 - 4] = [-1, -1]
"azy" => [25 - 0, 24 - 25] = [25, -1]
Example 3:
Input: @words = ("pop", "ada", "beb", "cfc")
Output: "pop"

"pop" => [14 - 15, 15 - 14] = [-1, 1]
"ada" => [3 - 0, 0 - 3] = [3, -3]
"beb" => [4 - 1, 1 - 4] = [3, -3]
"cfc" => [5 - 2, 2 - 5] = [3, -3]
Example 4:
Input: @words = ("aaaa", "zzzz", "mmmm", "aaba")
Output: "aaba"

"aaaa" => [0 - 0, 0 - 0, 0 - 0] = [0, 0, 0]
"zzzz" => [25 - 25, 25 - 25, 25 - 25] = [0, 0, 0]
"mmmm" => [12 - 12, 12 - 12, 12 - 12] = [0, 0, 0]
"aaba" => [0 - 0, 1 - 0, 0 - 1] = [0, 1, -1]
Example 5:
Input: @words = ("aceg", "bdfh", "cegi", "azbz")
Output: "azbz"

"aceg" => [2 - 0, 4 - 2, 6 - 4] = [2, 2, 2]
"bdfh" => [3 - 1, 5 - 3, 7 - 5] = [2, 2, 2]
"cegi" => [4 - 2, 6 - 4, 8 - 6] = [2, 2, 2]
"azbz" => [25 - 0, 1 - 25, 25 - 1] = [25, -24, 24]
File: string-difference
#! /usr/bin/env raku

unit sub MAIN (*@words where @words.elems > 0
                  && all(@words) ~~ /^ <[a..z]>**2..* $/
                  && ( [==] @words>>.chars ),
               :v(:$verbose));

my @signature = @words.map: { difference($_).raku };
my %count     = @signature.Bag;
my $index     = @signature.first: { %count{$_} == 1 }, :k;

if $verbose
{
  for @words -> $word
  {
    say ": $word => { difference($word).raku }";
  }
}

say @words[$index];

sub difference(Str $word)
{
  my @codes = $word.ords;
  my @diff = @codes[1..*] Z- @codes[0 ..^ @codes.elems - 1];
  @diff;
}

[3] A slurpy array of words, consisting of lowercase letters only, with at least one word, two letters in each word, and all the words must have the same length (the [==] part).

[8] Get the difference arrays for all the words, and stringifiy them with the raku method.

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

[9] Turn all the signature strings into a Bag, a hash like structure with a frequency count.

[10] Get the index of the first signature that occurs only once in the Bag. The :k adverb gives us the key (or index) instead of the actual value.

See docs.raku.org/routine/first for more information about first.

[20] Print the word with this index.

[22] Procedure calculating the string difference.

[23] Convert the string into a list of unicode codepoints with ords, the wholesale version of .ord.

See docs.raku.org/routine/ords for more information about ords.

See docs.raku.org/routine/ord for more information about ord.

[25] Compute the difference between each adjacent pair of letters, using the infix meta operator Z with minus to get the difference of the two values we "zip" together.

See docs.raku.org/routine/Z for more information about Z.

[26] Return the list of diffrences.

Running it:

$ ./string-difference ab bc cd zy
zy

$ ./string-difference cba fed azy
azy

$ ./string-difference pop ada beb cfc
pop

$ ./string-difference aaaa zzzz mmmm aaba
aaba

$ ./string-difference aceg bdfh cegi azbz
azbz

Looking good.

With verbose mode:

$ ./string-difference -v ab bc cd zy
: ab => [1]
: bc => [1]
: cd => [1]
: zy => [-1]
zy

$ ./string-difference -v cba fed azy
: cba => [-1, -1]
: fed => [-1, -1]
: azy => [25, -1]
azy

$ ./string-difference -v pop ada beb cfc
: pop => [-1, 1]
: ada => [3, -3]
: beb => [3, -3]
: cfc => [3, -3]
pop

$ ./string-difference -v aaaa zzzz mmmm aaba
: aaaa => [0, 0, 0]
: zzzz => [0, 0, 0]
: mmmm => [0, 0, 0]
: aaba => [0, 1, -1]
aaba

$ ./string-difference -v aceg bdfh cegi azbz
: aceg => [2, 2, 2]
: bdfh => [2, 2, 2]
: cegi => [2, 2, 2]
: azbz => [25, -24, 24]
azbz

And that's it.