Peter
Peter Campbell Smith

Foo meets Bar and
the wizardly trio

Weekly challenge 187 — 17 October 2022

Week 187 - 17 Oct 2022

Task 1

Task — Days together

Two friends, Foo and Bar gone on holidays seperately to the same city. You are given their schedule ie start date and end date. To keep the task simple, the date is in the form DD-MM and all dates belong to the same calendar year ie between 01-01 and 31-12. Also the year is a non-leap year and both dates are inclusive.

Write a script to find out for the given schedule, how many days they spent together in the city, if at all.

Examples


Example 1
Input: Foo => SD: '12-01' ED: '20-01'
       Bar => SD: '15-01' ED: '18-01'
Output: 4 days

Example 2
Input: Foo => SD: '02-03' ED: '12-03'
       Bar => SD: '13-03' ED: '14-03'
Output: 0 day

Example 3
Input: Foo => SD: '02-03' ED: '12-03'
       Bar => SD: '11-03' ED: '15-03'
Output: 2 days

Example 4
Input: Foo => SD: '30-03' ED: '05-04'
       Bar => SD: '28-03' ED: '02-04'
Output: 4 days

Analysis

We can easily see that the overlap is the later of their start dates to the earlier of their end dates, and its duration is simply the difference between these two day numbers, plus 1 - and if that is less than zero then - bad luck, Foo and Bar, you won't meet.

Try it 

Try running the script with any input:



example: 05-01, 19-01



example: 15-01, 20-01

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.28;    # The Weekly Challenge - 2022-10-17
use utf8;     # Week 187 - task 1 - Days together
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

my (@tests, $test);

@tests = ([qw[12-01 20-01 15-01 18-01]], [qw[02-03 12-03 13-03 14-03]], 
          [qw[02-03 12-03 11-03 15-03]], [qw[30-03 05-04 28-03 02-04]],
          [qw[01-01 31-12 01-01 31-12]], [qw[01-01 01-01 01-01 01-01]]);
for $test (@tests) {
    days_together($test);
}

sub days_together {
    
    my (@days_in_month, @tests, $test, $j, $day, $month, @day_of_year, 
    $start_together, $end_together, $time_together);

    @days_in_month = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    TEST: for $test (@_) {
        
        # show input
        say qq[\nInput: Foo => SD: '$test->[0]' ED: '$test->[1]'\n] .
              qq[       Bar => SD: '$test->[2]' ED: '$test->[3]'];
        
        # convert dates to day of year (1 Jan -> 1, 31 Dec -> 365)
        for $j (0 .. 3) {
            if ($test->[$j] =~ m|^(\d\d)\-(\d\d)$|) {
                ($day, $month) = ($1, $2);
                $day_of_year[$j] = $day;
                while ($month > 1) {
                    $day_of_year[$j] += $days_in_month[$month - 1];
                    $month --;
                }
            } else {
                say 'Invalid data';
                next TEST;
            }
        }
        
        # the overlap period is from the later of the starts and the earlier of the ends
        $start_together = $day_of_year[0] > $day_of_year[2] ? $day_of_year[0] : $day_of_year[2];
        $end_together = $day_of_year[1] < $day_of_year[3] ? $day_of_year[1] : $day_of_year[3];
        $time_together = $end_together - $start_together + 1;
        
        # if negative then there is no overlap
        $time_together = 0 if $time_together < 0;
        
        say qq[Output: $time_together day] . ($time_together == 1 ? '' : 's');
    }
}

Output


Input: Foo => SD: '12-01' ED: '20-01'
       Bar => SD: '15-01' ED: '18-01'
Output: 4 days

Input: Foo => SD: '02-03' ED: '12-03'
       Bar => SD: '13-03' ED: '14-03'
Output: 0 days

Input: Foo => SD: '02-03' ED: '12-03'
       Bar => SD: '11-03' ED: '15-03'
Output: 2 days

Input: Foo => SD: '30-03' ED: '05-04'
       Bar => SD: '28-03' ED: '02-04'
Output: 4 days

Input: Foo => SD: '01-01' ED: '31-12'
       Bar => SD: '01-01' ED: '31-12'
Output: 365 days

Input: Foo => SD: '01-01' ED: '01-01'
       Bar => SD: '01-01' ED: '01-01'
Output: 1 day