by Arne Sommer

# Greatest Target with Raku

[284] Published 12. April 2024.

This is my response to The Weekly Challenge #265.

## Challenge #265.1: Greatest English Letter

You are given a string, `\$str`, made up of only alphabetic characters `[a..zA..Z]`.

Write a script to return the greatest english letter in the given string.

A letter is greatest if it occurs as lower and upper case. Also letter ‘b’ is greater than ‘a’ if ‘b’ appears after ‘a’ in the English alphabet.

Example 1: ```Input: \$str = 'PeRlwEeKLy' Output: L There are two letters E and L that appears as lower and upper. The letter L appears after E, so the L is the greatest english letter. ``` Example 2: ```Input: \$str = 'ChaLlenge' Output: L ``` Example 3: ```Input: \$str = 'The' Output: '' ```
File: greatest-english-letter ```#! /usr/bin/env raku unit sub MAIN (Str \$str where \$str ~~ /^<[a..z A..Z]>+\$/, # [1] :v(:\$verbose)); my \$h = \$str.comb.Bag; # [2] say ": Bag: { \$h.raku }" if \$verbose; for 'Z' ... 'A' -> \$letter # [3] { say ": Checking \$letter" if \$verbose; if \$h{\$letter} && \$h{\$letter.lc} # [4] { say \$letter; # [4a] exit; # [4b] } } say ""; # [5] ```

[1] A string containing one or more lower- and uppercase english letters only.

[2] Turn the string into a list of characters (with `comb`) and that list into a `Bag` - a hash like structure where we can look up the letters easily.

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

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

[3] Iterate over uppercase letters, in descending order as we want the first match from the end of the alphabet.

[4] Do we have the letter itself and the lowercase version (with `lc`) in the Bag? If so, print the (uppercase) letter [4a] and finish [4b].

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

[5] No match; print an empty line.

Running it:

```\$ ./greatest-english-letter PeRlwEeKLy L \$ ./greatest-english-letter ChaLlenge L \$ ./greatest-english-letter The ```

Looking good.

With verbose mode:

```\$ ./greatest-english-letter -v PeRlwEeKLy : Bag: ("P"=>1,"l"=>1,"y"=>1,"K"=>1,"e"=>2,"E"=>1,"R"=>1,"w"=>1,"L"=>1).Bag : Hash: {:E(1), :K(1), :L(1), :P(1), :R(1), :e(2), :l(1), :w(1), :y(1)} : Checking Z : Checking Y : Checking X : Checking W : Checking V : Checking U : Checking T : Checking S : Checking R : Checking Q : Checking P : Checking O : Checking N : Checking M : Checking L L \$ ./greatest-english-letter -v ChaLlenge : Bag: ("g"=>1,"h"=>1,"e"=>2,"C"=>1,"a"=>1,"n"=>1,"L"=>1,"l"=>1).Bag : Checking Z : Checking Y : Checking X : Checking W : Checking V : Checking U : Checking T : Checking S : Checking R : Checking Q : Checking P : Checking O : Checking N : Checking M : Checking L L \$ ./greatest-english-letter -v The : Bag: ("h"=>1,"T"=>1,"e"=>1).Bag : Checking Z : Checking Y : Checking X : Checking W : Checking V : Checking U : Checking T : Checking S : Checking R : Checking Q : Checking P : Checking O : Checking N : Checking M : Checking L : Checking K : Checking J : Checking I : Checking H : Checking G : Checking F : Checking E : Checking D : Checking C : Checking B : Checking A ```

Note that we have two lowercase «e»s in the second example, and the `Bag` has that information readily available. (Even if we do not care here.)

## Challenge #265.2: Target Array

You are given two arrays of integers, `@source` and `@indices`. The `@indices` can only contains integers `0 <= i < size of @source`.

Write a script to create target array by insert at index `\$indices[i]` the value `\$source[i]`.

Example 1: ```Input: @source = (0, 1, 2, 3, 4) @indices = (0, 1, 2, 2, 1) Output: (0, 4, 1, 3, 2) @source @indices @target 0 0 (0) 1 1 (0, 1) 2 2 (0, 1, 2) 3 2 (0, 1, 3, 2) 4 1 (0, 4, 1, 3, 2) ``` Example 2: ```Input: @source = (1, 2, 3, 4, 0) @indices = (0, 1, 2, 3, 0) Output: (0, 1, 2, 3, 4) @source @indices @target 1 0 (1) 2 1 (1, 2) 3 2 (1, 2, 3) 4 3 (1, 2, 3, 4) 0 0 (0, 1, 2, 3, 4) ``` Example 3: ```Input: @source = (1) @indices = (0) Output: (1) ```
File: target-array ```#! /usr/bin/env raku unit sub MAIN (\$source, \$indices, :v(:\$verbose)); # [1] my @source = \$source.words>>.Int; # [2] my @indices = \$indices.words>>.UInt; # [3] die "Note the same number of elems" unless @source.elems == @indices.elems; # [4] die "Index too large" if @indices.max > @indices.elems; # [5] my @target; # [6] for ^@indices.elems -> \$index # [7] { say ": Source:@source[\$index] Index:@indices[\$index]" if \$verbose; @target.splice(@indices[\$index], 0, @source[\$index]); # [8] } say "({ @target.join(",") })"; # [9] ```

[1] The source array, as a space separated string. Followed by the index array, also as a space separated string.

[2] Convert the source string into an array of integers. Note that the `.Int` coersion will turn non-integer numeric values into integers. Feel free to consider that a feature, or an arror.

[3] Ditto for the index string, except that we use `.UInt` to ensure unsigned integers, as negative indices will not do.

[4] The two arrays must have the same length.

[5] The highest index value (with `max`) must be a valid index in the array(s).

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

[6] The target values will end up here.

[7] For each index (0 .. <last index in the array>, and not the content of `@indices`).

[8] Use `splice` to insert the source value (`@source[\$index]`) at index position `@indices[\$index]`, moving any values at that index and after to the right. The zero means that we are to remove no values (i.e. replacing instead of inserting).

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

[9] Pretty print the result.

Running it:

```\$ ./target-array "0 1 2 3 4" "0 1 2 2 1" (0,4,1,3,2) \$ ./target-array "1 2 3 4 0" "0 1 2 3 0" (0,1,2,3,4) \$ ./target-array "1" "0" (1) ```

Looking good.

With verbose mode:

```\$ ./target-array -v "0 1 2 3 4" "0 1 2 2 1" : Source:0 Index:0 : Source:1 Index:1 : Source:2 Index:2 : Source:3 Index:2 : Source:4 Index:1 (0,4,1,3,2) \$ ./target-array -v "1 2 3 4 0" "0 1 2 3 0" : Source:1 Index:0 : Source:2 Index:1 : Source:3 Index:2 : Source:4 Index:3 : Source:0 Index:0 (0,1,2,3,4) \$ ./target-array -v "1" "0" : Source:1 Index:0 (1) ```

And that's it.