with Raku

This is my response to The Weekly Challenge #276.

You are given an array of integers,

Write a script to return the number of pairs that forms a complete day.

A complete day is defined as a time duration that is an exact multiple of 24 hours.

Example 1:

`@hours`

.
Write a script to return the number of pairs that forms a complete day.

A complete day is defined as a time duration that is an exact multiple of 24 hours.

Example 1:

Input: @hours = (12, 12, 30, 24, 24)
Output: 2
Pair 1: (12, 12)
Pair 2: (24, 24)

Example 2:
Input: @hours = (72, 48, 24, 5)
Output: 3
Pair 1: (72, 48)
Pair 2: (72, 24)
Pair 3: (48, 24)

Example 3:
Input: @hours = (12, 18, 24)
Output: 0

File: complete-day

#! /usr/bin/env raku
unit sub MAIN (*@hours where all(@hours) ~~ UInt && @hours.elems > 1, # [1]
:v(:$verbose));
my $pairs = 0; # [2]
for @hours.combinations(2) -> ($first, $second) # [3]
{
next if $first == $second == 0; # [4]
if ($first + $second) %% 24 # [5]
{
$pairs++; # [5a]
say ": Pair $pairs: ($first, $second)" if $verbose;
}
}
say $pairs; # [6]

[1] Ensure that all the hour values are unsigned integers (the `UInt`

type), i.e. not negative, and that we have at least two of them.

[2] The result will end up here.

[3] Iterate over all the `combinations`

of two
values from the input. We put the two values in their own variables instead
of an array, just for fun.

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

.

[4] Skip the current combination if both values are zero, as
`0 %% 24 -> True`

and that will screw up the check in [5].

[5] Add the two values and check if the result is divisible (`%%`

) by
24. Increase the counter if it is [5a].

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

.

[6] Print the result.

Running it:

$ ./complete-day 12 12 30 24 24
2
$ ./complete-day 72 48 24 5
3
$ ./complete-day 12 18 24
0

Looking good.

With verbose mode:

$ ./complete-day -v 12 12 30 24 24
: Pair 1: (12, 12)
: Pair 2: (24, 24)
2
$ ./complete-day -v 72 48 24 5
: Pair 1: (72, 48)
: Pair 2: (72, 24)
: Pair 3: (48, 24)
3
$ ./complete-day -v 12 18 24
0

Zeroes are fine:

$ ./complete-day -v 0 0 12 24
: Pair 1: (0, 24)
: Pair 2: (0, 24)
2
$ ./complete-day -v 0 0 12
0

You are given an array of positive integers,

Write a script to return the total number of elements in the given array which have the highest frequency.

Example 1:

File: maximum-frequency
`@ints`

.
Write a script to return the total number of elements in the given array which have the highest frequency.

Example 1:

Input: @ints = (1, 2, 2, 4, 1, 5)
Ouput: 4
The maximum frequency is 2.
The elements 1 and 2 has the maximum frequency.

Example 2:
Input: @ints = (1, 2, 3, 4, 5)
Ouput: 5
The maximum frequency is 1.
The elements 1, 2, 3, 4 and 5 has the maximum frequency.

#! /usr/bin/env raku
unit sub MAIN (*@ints where all(@ints) ~~ Int
&& all(@ints) > 0
&& @ints.elems > 0, # [1]
:v(:$verbose));
my $bag = @ints.Bag; # [2]
my $max-freq = $bag.values.max; # [3]
say ": The maximum frequency is $max-freq" if $verbose;
say $bag.grep( *.value == $max-freq ) * $max-freq; # [4]

[1] Ensure at least one element, all of which are positive integers.

[2] Turn the input inta a `Bag`

, a hash like structure
that counts the frequency of each distinct value.

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

.

[3] Then we apply `values`

to get the frequencies (of the distinct
values), and `max`

to get the highest one.

[4] Use `grep`

to get the highest frequencies (as there may be more
than one). The result is still a Bag, which is then coerced to its length
when we use it in numeric context. Then we multiply this with the highest
value (the frequency of each one) to get the result - which we print.

Running it:

$ ./maximum-frequency 1 2 2 4 1 5
4
$ ./maximum-frequency 1 2 3 4 5
5

Looking good.

With verbose mode:

$ ./maximum-frequency -v 1 2 2 4 1 5
: The maximum frequency is 2
4
$ ./maximum-frequency -v 1 2 3 4 5
: The maximum frequency is 1
5

And that's it.