La La Three
with Raku

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.