by Arne Sommer

# LaLa Three with Raku

[265] Published 3. December 2023.

This is my response to The Weekly Challenge #245.

## Challenge #245.1: Sort Language

You are given two array of languages and its popularity.

Write a script to sort the language based on popularity.

Example 1: ```Input: @lang = ('perl', 'c', 'python') @popularity = (2, 1, 3) Output: ('c', 'perl', 'python') ``` Example 2: ```Input: @lang = ('c++', 'haskell', 'java') @popularity = (1, 3, 2) Output: ('c++', 'java', 'haskell') ```
File: sort-language ```#! /usr/bin/env raku unit sub MAIN ( \$popularity, # [1] *@lang where @lang.elems == \$popularity.words.elems > 0, # [2] && \$popularity.words.repeated.elems == 0 # [2a] && \$popularity.words.min == 1 # [2b] && \$popularity.words.max == \$popularity.words.elems, # [2c] :v(:\$verbose) ); my @popularity = \$popularity.words>>.Int; # [3] my %popularity; # [4] for ^@popularity -> \$index # [5] { %popularity{@lang[\$index]} = @popularity[\$index]; # [6] say ": Language '{ @lang[\$index] } with popularity { @popularity[\$index] }" if \$verbose; } my @output = @lang.sort({ %popularity{\$^a} <=> %popularity{\$^b} }); # [7] say "(" ~ @output.map({ "'\$_'" }).join(", ") ~ ")"; # [8] ```

[1] Specify the popularity as the first argument, a quoted space separated string.

[2] Followed by the languages. Note the check on the number of languages (at least one), and the same number of them as given in [1]. Then we check that they are all unique [2a] (by ensuring that there are no duplicates (with `repeated`), and that the first one has the value 1 [2b], and the last one has the value of the length of the language array - thus ensureing that all the popularity values are given.

{{repeated]]

[3] Split the popularity string (with `words`), and coerce all the resulting strings to integers (so that verbose mode looks nicer).

[4] We are going to build up the popularity here; the language as key, and the popularity number as value.

[5] Iterate over the indices for the polularity.

[6] Set up the mapping from the langue to the popularity.

[7] Sort the languages on their popularity.

[8] Pretty print the result.

Running it:

```\$ ./sort-language "2 1 3" perl c python ('c', 'perl', 'python') \$ ./sort-language "1 3 2" c++ haskell java ('c++', 'java', 'haskell') ```

Looking good.

With verbose mode:

```\$ ./sort-language -v "2 1 3" perl c python : Language 'perl with popularity 2 : Language 'c with popularity 1 : Language 'python with popularity 3 ('c', 'perl', 'python') \$ ./sort-language -v "1 3 2" c++ haskell java : Language 'c++ with popularity 1 : Language 'haskell with popularity 3 : Language 'java with popularity 2 ('c++', 'java', 'haskell') ```

## Challenge #245.2: Largest of Three

You are given an array of integers >= 0.

Write a script to return the largest number formed by concatenating some of the given integers in any order which is also multiple of 3. Return -1 if none found.

Example 1: ```Input: @ints = (8, 1, 9) Output: 981 981 % 3 == 0 ``` Example 2: ```Input: @ints = (8, 6, 7, 1, 0) Output: 8760 ``` Example 3: ```Input: @ints = (1) Output: -1 ```
File: largest-of-three ```#! /usr/bin/env raku unit sub MAIN (*@ints where @ints.elems >= 1 && all(@ints) ~~ UInt, # [1] :v(:\$verbose)); my \$largest = -1; # [2] for @ints.combinations(1..Inf) -> @combination # [3] { say ":Combination: @combination[]" if \$verbose; for @combination.permutations.unique(:with(&[eqv])) -> @permutation # [4] { my \$candidate = @permutation.join; # [5] my \$is-three = \$candidate %% 3; # [6] if \$is-three # [7] { \$largest = max(\$largest, \$candidate); # [7a] say ": - Permutation: @permutation[] -> \$candidate %% 3" if \$verbose; } else { say ": - Permutation: @permutation[] -> \$candidate" if \$verbose; } } } say \$largest; # [8] ```

[1] At last one element, and they must all be non negative integers (the UInt; Unsigned Int type).

[2] Initial value, and the result if we do not have any match(es). Any matching value will be higher.

[3] Use `combinations` to get all the combinations. Note the array slice to get rid of the first combination, as that is an empty list

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

[4] Iterate over all the permutations, and get rid of duplicates (with `:with(&[eqv]`) in case we had duplicates in the input array.

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

[5] Join the values together to form a single value.

[6] Is it divisible by 3? (Note the divisibility operator `%%`.)

See docs.raku.org/routine/%% for more information about the Divisibility Operator `%%`.

[7] If yes, set the maximum value to the largest of this one and the old value with `max`[7a].

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

[8] Pretty print the result.

Running it:

```\$ ./largest-of-three 8 1 9 981 \$ ./largest-of-three 8 6 7 1 0 8760 \$ ./largest-of-three 1 -1 ```

Looking good.

With verbose mode, for the first example only:

```\$ ./largest-of-three -v 8 1 9 :Combination: 8 : - Permutation: 8 -> 8 :Combination: 1 : - Permutation: 1 -> 1 :Combination: 9 : - Permutation: 9 -> 9 %% 3 :Combination: 8 1 : - Permutation: 8 1 -> 81 %% 3 : - Permutation: 1 8 -> 18 %% 3 :Combination: 8 9 : - Permutation: 8 9 -> 89 : - Permutation: 9 8 -> 98 :Combination: 1 9 : - Permutation: 1 9 -> 19 : - Permutation: 9 1 -> 91 :Combination: 8 1 9 : - Permutation: 8 1 9 -> 819 %% 3 : - Permutation: 8 9 1 -> 891 %% 3 : - Permutation: 1 8 9 -> 189 %% 3 : - Permutation: 1 9 8 -> 198 %% 3 : - Permutation: 9 8 1 -> 981 %% 3 : - Permutation: 9 1 8 -> 918 %% 3 981 ```

And that's it.