Complete Maximum
with Raku

by Arne Sommer

Complete Maximum with Raku

[296] Published 7. July 2024.

This is my response to The Weekly Challenge #276.

Challenge #276.1: Complete Day

You are given an array of integers, @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

Challenge #276.2: Maximum Frequency

You are given an array of positive integers, @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.
File: 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.