This is my response to The Weekly Challenge #245.
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')
#! /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.
[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')
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
#! /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.