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.
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 "
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.