Spaces at Large
with Raku

by Arne Sommer

Spaces at Large with Raku

[396] Published 10. May 2026.

This is my response to The Weekly Challenge #372.

I have changed the presentation of the code to use syntax highlighting (with shiki), after a request on Reddit last week. The old manually added numbered comments in the code itself have gone, replaced by using the actual line numbers.

#372.1 Rearrange Spaces You are given a string text of words that are placed among number of spaces.

Write a script to rearrange the spaces so that there is an equal number of spaces between every pair of adjacent words and that number is maximised. If you can't distribute, place the extra spaces at the end. Finally return the string.

Example 1:
Input: $str = "  challenge  "
Output: "challenge    "

We have 4 spaces and 1 word. So all spaces go to the end.
Example 2:
Input: $str = "coding  is  fun"
Output: "coding  is  fun"

We have 4 spaces and 3 words (2 gaps). So 2 spaces per gap.
Example 3:
Input: $str = "a b c  d"
Output: "a b c d "

We have 4 spaces and 4 words (3 gaps). So 1 space per gap and 1
remainder.
Example 4:
Input: $str = "  team      pwc  "
Output: "team          pwc"

We have 10 spaces and 2 words (1 gap). So 10 spaces per gap.

Example 5
Example 5:
Input: $str = "   the  weekly  challenge  "
Output: "the    weekly    challenge "

We have 9 spaces and 3 words (2 gaps). So 4 spaces per gap and 1
remainder.

File: rearrange-spaces
#! /usr/bin/env raku

unit sub MAIN ($str where $str.chars > 0,
               :v(:$verbose));

my @words  = $str.words;
my $words  = @words.elems;
my $spaces = $str.comb.grep( * eq " " ).elems;

my $fill   = $words == 1 ?? 0 !! $spaces div ($words - 1);
my $trail  = $words == 1 ?? $spaces
                         !! $spaces - $fill * ($words - 1);

say ":w:$words s:$spaces f:$fill t:$trail" if $verbose;

say '"' ~ @words.join(" " x $fill) ~ (" " x $trail) ~ '"';

[3] A string with at least 1 character.

[6] Get the individual words,

[7] and the number of them.

[8] Get the total number of spaces in the original string, using comb to get a list of single characters, then grep to only keep the spaces, and finally elems to count them.

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

[10] The number of spaces to use (as filler) between each word.

[11] The number of remaining spaces, to use after the last word (as trailing spaces).

[16] Print the result, with filler and trailing spaces.

Running it:

$ ./rearrange-spaces "  challenge  "
"challenge    "

$ ./rearrange-spaces "coding  is  fun"
"coding  is  fun"

$ ./rearrange-spaces "a b c  d"
"a b c d "

$ ./rearrange-spaces "  team      pwc  "
"team          pwc"

$ ./rearrange-spaces "   the  weekly  challenge  "
"the    weekly    challenge "

Looking good.

With verbose mode:

$ ./rearrange-spaces -v "  challenge  "
:w:1 s:4 f:0 t:4
"challenge    "

$ ./rearrange-spaces -v "coding  is  fun"
:w:3 s:4 f:2 t:0
"coding  is  fun"

$ ./rearrange-spaces -v "a b c  d"
:w:4 s:4 f:1 t:1
"a b c d "

$ ./rearrange-spaces -v "  team      pwc  "
:w:2 s:10 f:10 t:0
"team          pwc"

$ ./rearrange-spaces -v "   the  weekly  challenge  "
:w:3 s:9 f:4 t:1
"the    weekly    challenge "

#372.2 Largest Substring You are given a string.

Write a script to return the length of the largest substring between two equal characters excluding the two characters. Return -1 if there is no such substring.

Example 1:
Input: $str = "aaaaa"
Output: 3

For character "a", we have substring "aaa".
Example 2:
Input: $str = "abcdeba"
Output: 5

For character "a", we have substring "bcdeb".
Example 3:
Input: $str = "abbc"
Output: 0

For character "b", we have substring "".
Example 4:
Input: $str = "abcaacbc"
Output: 4

For character "a", we have substring "bca".
For character "b", we have substring "caac".
For character "c", we have substring "aacb".
Example 5:
Input: $str = "laptop"
Output: 2

For character "p", we have substring "to".

File: largest-substring
#! /usr/bin/env raku

unit sub MAIN ($str where $str.chars > 0,
               :v(:$verbose));

my @chars = $str.comb.Bag.grep({ .value > 1 })>>.key.sort;

say ":Duplicate characters (sorted): \
 { @chars.map({ "«$_»" }).join(", ")}" if $verbose;

my $max = 0;

for @chars -> $char
{
  my $first  = $str.index($char);
  my $last   = $str.rindex($char);
  my $length = $last - $first - 1;
  my $is-max = $length > $max;
  
  say ":Char «$char» at pos $first and $last -> \
    «{ $str.substr($first + 1, $length) }» with length $length \
    { $is-max ?? "- new max" !! "" }" if $verbose;

  $max = $length if $is-max;
}

say $max;

[3] A string with at least 1 character.

[6] Get a list of repeating characterts (using a Bag and keeping only those that have a count larger than 1), sorted alphabetically.

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

[11] The result will end up here.

[13] Iterate over the candidate characters (those that repeated themselves).

[15] Get the index (with index) of the first occurence of the character in the string.

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

[16] Get the index (with rindex) of the last occurence of the character in the string.

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

[17] Get the length of the substring, not including the characters (found in [15] and [16]) themselves.

[18] Do we have a new maximim?

[24] Update the maximum, if so.

[27] Print the result.

Running it:

$ ./largest-substring "aaaaa"
3

$ ./largest-substring "abcdeba"
5

$ ./largest-substring "abbc"
0

$ ./largest-substring "abcaacbc"
4

$ ./largest-substring "laptop"
2

Looking good.

With verbose mode:

$ ./largest-substring -v "aaaaa"
:Duplicate characters (sorted): «a»
:Char «a» at pos 0 and 4 -> «aaa» with length 3 - new max
3

$ ./largest-substring -v "abcdeba"
:Duplicate characters (sorted): «a», «b»
:Char «a» at pos 0 and 6 -> «bcdeb» with length 5 - new max
:Char «b» at pos 1 and 5 -> «cde» with length 3 
5

$ ./largest-substring -v "abbc"
:Duplicate characters (sorted): «b»
:Char «b» at pos 1 and 2 -> «» with length 0 
0

$ ./largest-substring -v "abcaacbc"
:Duplicate characters (sorted): «a», «b», «c»
:Char «a» at pos 0 and 4 -> «bca» with length 3 - new max
:Char «b» at pos 1 and 6 -> «caac» with length 4 - new max
:Char «c» at pos 2 and 7 -> «aacb» with length 4 
4

$ ./largest-substring -v "laptop"
:Duplicate characters (sorted): «p»
:Char «p» at pos 2 and 5 -> «to» with length 2 - new max
2

And that's it.