with Raku

This is my response to The Weekly Challenge #195.

You are given a positive integer,

Write a script to print the count of all special integers between

An integer is special when all of its digits are unique.

Example 1:

`$n > 0`

.
Write a script to print the count of all special integers between

`1`

and `$n`

.
An integer is special when all of its digits are unique.

Example 1:

Input: $n = 15
Output: 14 as except 11 all other integers between 1 and 15 are spcial.

Example 2:
Input: $n = 35
Output: 32 as except 11, 22, 33 all others are special.

This resembles last week's
Frequency Equalizer (#194.2), with calculation
of character frequencies within a string. The `Bag`

approach is equally
suitable here:

unit sub MAIN (Int $n where $n > 0, :v(:$verbose)); # [1]
my $count = 0; # [2]
for 1 .. $n -> $candidate # [3]
{
my $special = is-special($candidate); # [4]
$count++ if $special; # [6]
say ": $candidate { "special" if $special }" if $verbose;
}
say $count; # [7]
sub is-special ($integer) # [5]
{
return all($integer.comb.Bag.values) == 1; # [5]
}

[1] Ensure that we get a positive integer.

[2] We are going to count the special integers, one at a time.

[3] Iterate over the values in the range (1 - upper limit).

[4] Is it a special integer?

[5]
Turn the number into a list of single characters (with `comb`

).
Then turn that list into a `Bag`

, a hash like structure where the values in the
input list is the keys, and the frequency of each element is the value. Then we use an
`all`

junction to ensure that all the frequencies (with `values`

)
are equal to 1.

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

type.

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

Junction.

[6] Add to the counter, if it is special.

[7] Print the count.

Running it:

$ ./special-integers 15
14
$ ./special-integers 35
32

Looking good.

With verbose mode:

$ ./special-integers -v 15
: 1 special
: 2 special
: 3 special
: 4 special
: 5 special
: 6 special
: 7 special
: 8 special
: 9 special
: 10 special
: 11
: 12 special
: 13 special
: 14 special
: 15 special
14
$ ./special-integers -v 35
: 1 special
: 2 special
: 3 special
: 4 special
: 5 special
: 6 special
: 7 special
: 8 special
: 9 special
: 10 special
: 11
: 12 special
: 13 special
: 14 special
: 15 special
: 16 special
: 17 special
: 18 special
: 19 special
: 20 special
: 21 special
: 22
: 23 special
: 24 special
: 25 special
: 26 special
: 27 special
: 28 special
: 29 special
: 30 special
: 31 special
: 32 special
: 33
: 34 special
: 35 special
32

You are given a list of numbers,

Write a script to find most frequent even numbers in the list. In case you get more than one even numbers then return the

Example 1:

File: most-frequent-even
`@list`

.
Write a script to find most frequent even numbers in the list. In case you get more than one even numbers then return the

`smallest even integer`

. For all
other case, return `-1`

.
Example 1:

Input: @list = (1,1,2,6,2)
Output: 2 as there are only 2 even numbers 2 and 6 and of those 2
appears the most.

Example 2:
Input: @list = (1,3,5,7)
Output: -1 since no even numbers found in the list

Example 3:
Input: @list = (6,4,4,6,1)
Output: 4 since there are only two even numbers 4 and 6. They both
appears the equal number of times, so pick the smallest.

#! /usr/bin/env raku
unit sub MAIN (*@list where @list.elems > 0 # [1]
&& all(@list) ~~ /^<[1..9]><[0..9]>*$/, :v(:$verbose));
my @even = @list.grep: * %% 2; # [2]
if @even.elems # [3]
{
my $bag = @even.Bag; # [4]
my $max = $bag.values.max; # [5]
my $res = $bag.grep({ $_.value == $max }); # [6]
my @sorted = $res>>.key.sort; # [7]
if $verbose
{
say ":Even: @even[]"; # [4a]
say ":Max: $max"; # [5a]
say ":Sorted: @sorted[]"; # [7a]
}
say @sorted.first; # [8]
}
else
{
say ":No even integers" if $verbose;
say -1; # [9]
}

[1] Ensure at least 1 element, and that all of them are positive integers.

[2] Get the even integers, using `grep`

and the divisibilty
operator `%%`

.

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

.

[3] Do we have any even elements at all?

[4] Turn the values into a `Bag`

.

[5] Get the highest frequency (the `value`

part of the Bag).

[6] Get the Bag entries with the highest frequency (as calculated in [5]). There may be more than one.

[7] Get all the keys (i.e. integers from `@list`

), applied individually on each
Bag entry (a Pair) with `>>.key`

, in sorted order.

[8] The first one in either the only one, or the lowest value.

[9] No even elements? Print «-1» and we are done.

Running it:

$ ./most-frequent-even 1 1 2 6 2
2
$ ./most-frequent-even 1 3 5 7
-1
$ ./most-frequent-even 6 4 4 6 1
4

Looking good.

With verbose mode:

$ ./most-frequent-even -v 1 1 2 6 2
:Even: 2 6 2
:Max: 2
:Sorted: 2
2
$ ./most-frequent-even -v 1 3 5 7
:No even integers
-1
$ ./most-frequent-even -v 6 4 4 6 1
:Even: 6 4 4 6
:Max: 2
:Sorted: 4 6
4

And that's it.