Perl Weekly Challenge 276.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 276.
Task 1: Complete Day
Submitted by: Mohammad Sajid Anwar
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
A pair of hours adds to a complete day if their sum is zero
modulo 24. I can make an array $N[$h]
with the
number of hours
that equal $h
mod 24, all of which pair with
(-$h)%24
. Thus, the corresponding number of pairs is
$N[$h]*$N[-$h%24]
. After adding over all possible values of
$h=0..23
I would have to divide by 2, to avoid counting every pair
twice. Instead, I can choose $h<=12$
so that $(-$h)%24 >=12
.
There are two exceptions, $h=0
and $h=12
, for which
$h==(-$h)%24
. In those cases I should remove an element pairing with
itself, so their contribution to the number of pairs is
$N[$h]*($N[$h]-1)/2
instead. The result fits a longish
one-liner. Notice that I consider zero hours as a complete, though
rather short, day.
Example 1:
perl -E '
$N[$_%24]++for@ARGV;$t+=$N[$_]*$N[(-$_)%24]for 1..11;$t+=$N[$_]*($N[$_]-1)/2for(0,12);say"@ARGV -> $t"
' 12 12 30 24 24
Results:
12 12 30 24 24 -> 2
Example 2:
perl -E '
$N[$_%24]++for@ARGV;$t+=$N[$_]*$N[(-$_)%24]for 1..11;$t+=$N[$_]*($N[$_]-1)/2for(0,12);say"@ARGV -> $t"
' 72 48 24 5
Results:
72 48 24 5 -> 3
Example 3:
perl -E '
$N[$_%24]++for@ARGV;$t+=$N[$_]*$N[(-$_)%24]for 1..11;$t+=$N[$_]*($N[$_]-1)/2for(0,12);say"@ARGV -> $t"
' 12 18 24
Results:
12 18 24 -> 0
The full code is:
1 # Perl weekly challenge 276
2 # Task 1: Complete Day
3 #
4 # See https://wlmb.github.io/2024/07/01/PWC276/#task-1-complete-day
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 H1 H2...
8 to find how many pairs of hours H1, H2... add up to complete days.
9 FIN
10 my @counts;
11 $counts[$_%24]++ for @ARGV;
12 my $Npairs;
13 $Npairs += ($counts[$_]//0)*($counts[(-$_)%24]//0) for 1..11;
14 $Npairs += ($counts[$_]//0)*(($counts[$_]//0)-1)/2 for(0,12);
15 say "@ARGV -> $Npairs";
Examples:
./ch-1.pl 12 12 30 24 24
./ch-1.pl 72 48 24 5
./ch-1.pl 12 18 24
Results:
12 12 30 24 24 -> 2
72 48 24 5 -> 3
12 18 24 -> 0
Task 2: Maximum Frequency
Submitted by: Mohammad Sajid Anwar
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.
I make a hash with the frequencies of each int, find the max, use it to filter the ints and count how many of them have the max frequency. The result fits a oneliner.
Example 1:
perl -MList::AllUtils=max -E '
$N{$_}++ for @ARGV; $m=max values %N; say "@ARGV -> ", $m*grep{$N{$_}==$m}keys %N
' 1 2 2 4 1 5
Results:
1 2 2 4 1 5 -> 4
Example 2:
perl -MList::AllUtils=max -E '
$N{$_}++ for @ARGV; $m=max values %N; say "@ARGV -> ", $m*grep{$N{$_}==$m}keys %N
' 1 2 3 4 5
Results:
1 2 3 4 5 -> 5
The corresponding full code is:
1 # Perl weekly challenge 276
2 # Task 2: Maximum Frequency
3 #
4 # See https://wlmb.github.io/2024/07/01/PWC276/#task-2-maximum-frequency
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 N1 N2...
8 to count how many numbers N1, N2... appear with the maximum frequency.
9 FIN
10 my %counts;
11 $counts{$_}++ for @ARGV;
12 my $max=max values %N;
13 say "@ARGV -> ", $max*grep{$N{$_}==$max} keys %counts
Examples:
./ch-2.pl 1 2 2 4 1 5
./ch-2.pl 1 2 3 4 5