Perl Weekly Challenge 276: Complete Day

These are some answers to the Week 276, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on July 7, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 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

Complete Day in Raku

I have been trying to think about more clever solutions, but they quickly turned out to be far too complicated. By contrast, the brute force approach is very simple: we simply generate all possible pairs (with the combinations method) and keep the count of those whose sum is evenly divided by 24.

sub complete-day (@in) {
    my $count = 0;
    for @in.combinations: 2 -> @pair {
        $count++ if ([+] @pair) %% 24;
    }
    return $count;

my @tests = <12 12 30 24 24>, <72 48 24 5>, <12 18 24>;
for @tests -> @test {
    printf "%-15s => ", "@test[]";
    say complete-day @test;
}

This program displays the following output:

$ raku ./complete-days.raku
12 12 30 24 24  => 2
72 48 24 5      => 3
12 18 24        => 0

Complete Day in Perl

This is a port to Perl of the above Raku program. However, since Perl doesn't have a built-in combinations function, we generate all possible pairs "by hand" with nested loops.

use strict;
use warnings;
use feature 'say';


sub complete_day {
    my @in = @_;
    my $count = 0;
    for my $i (0..$#in) {
        for my $j ($i+1..$#in) {
            $count++ if ($in[$i] + $in[$j]) % 24 == 0;
        }
    }
    return $count;
}

my @tests = ([<12 12 30 24 24>], [<72 48 24 5>], [<12 18 24>]);
for my $test (@tests) {
    printf "%-15s => ", "@$test";
    say complete_day @$test;
}

This program displays the following output:

$ perl ./complete-days.pl
12 12 30 24 24  => 2
72 48 24 5      => 3
12 18 24        => 0

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on July 14, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.