aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorboblied <boblied@gmail.com>2023-02-28 07:36:58 -0600
committerboblied <boblied@gmail.com>2023-03-05 09:46:31 -0600
commitfe703324d30638201357c25be6fa24c6fc7ff11a (patch)
treeed2c21d79c2323760da60764c12f7bd4f2d74bb0
parent67c3eb984b684e9bc48cd7a2de9dc4487226e70c (diff)
downloadperlweeklychallenge-club-fe703324d30638201357c25be6fa24c6fc7ff11a.tar.gz
perlweeklychallenge-club-fe703324d30638201357c25be6fa24c6fc7ff11a.tar.bz2
perlweeklychallenge-club-fe703324d30638201357c25be6fa24c6fc7ff11a.zip
Week 206 Task 1
-rw-r--r--challenge-206/bob-lied/perl/ch-1.pl85
1 files changed, 85 insertions, 0 deletions
diff --git a/challenge-206/bob-lied/perl/ch-1.pl b/challenge-206/bob-lied/perl/ch-1.pl
new file mode 100644
index 0000000000..b803fb3d44
--- /dev/null
+++ b/challenge-206/bob-lied/perl/ch-1.pl
@@ -0,0 +1,85 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# ch-1.pl Perl Weekly Challenge Week 206 Task 1 Shortest Time
+#=============================================================================
+# Copyright (c) 2023, Bob Lied
+#=============================================================================
+# You are given a list of time points, at least 2, in the 24-hour clock format
+# HH:MM. Write a script to find out the shortest time in minutes between any
+# two time points.
+# Example 1 Input: @time = ("00:00", "23:55", "20:00") Output: 5
+# Since the difference between "00:00" and "23:55" is the shortest
+# Example 2 Input: @array = ("01:01", "00:50", "00:57") Output: 4
+# Example 3 Input: @array = ("10:10", "09:30", "09:00", "09:55") Output: 15
+##
+# Example 1 implies that 00:00 can represent midnight either at the start
+# of the day, or at the end of the day. Ambiguous if 24:00 is allowed.
+#
+# All the interesting times involve midnight. If all the
+# points were within the same day, then a pair like 00:10, 23:50 would be
+# 23 hours and 40 minutes long. But if we allow wrapping around midnight,
+# there's only 20 minutes between them. The problem specification is
+# ambiguously silent, except that example with 00:00 kind of implies that
+# we should wrap around.
+#=============================================================================
+
+use v5.36;
+
+use List::Util qw/min/;
+
+use constant {
+ MINPERDAY => 24 * 60
+};
+
+use Getopt::Long;
+my $Verbose = 0;
+my $DoTest = 0;
+
+GetOptions("test" => \$DoTest, "verbose" => \$Verbose);
+exit(!runTest()) if $DoTest;
+
+# Map a string in HH:MM format to the minute past midnight.
+sub hhmmToMin($hhmm)
+{
+ my ($hour, $min) = split(':', $hhmm);
+ my $minOfDay = $hour * 60 + $min;
+ return ($minOfDay == MINPERDAY ? 0 : $minOfDay);
+}
+
+sub shortestTime($moments)
+{
+ my @minutes = map { hhmmToMin($_) } $moments->@*;
+
+ my $least = MINPERDAY;
+
+ # Do a full NxN scan of every possible pair. Getting the difference
+ # in either direction will wash away the ambiguity of 00:00.
+ for ( my $beg = 0 ; $beg <= $#minutes ; $beg++ )
+ {
+ for ( my $end = 0; $end <= $#minutes ; $end++ )
+ {
+ next if $end == $beg;
+ my $d1 = ( $minutes[$end] - $minutes[$beg] ) % MINPERDAY;
+ $least = min($least, $d1 );
+ }
+ }
+ return $least;
+}
+
+sub runTest
+{
+ use Test2::V0;
+
+ is( shortestTime( [ "00:00", "23:55", "20:00" ] ), 5, "Example 1");
+ is( shortestTime( [ "01:01", "00:50", "00:57" ] ), 4, "Example 2");
+ is( shortestTime( [ "10:10", "09:30", "09:00", "09:55" ] ), 15, "Example 3");
+
+ is( shortestTime( [ "00:02", "23:58", "00:57" ] ), 4, "'round midnight");
+ is( shortestTime( [ "00:02", "00:57", "00:02" ] ), 0, "Zero");
+ is( shortestTime( [ "23:55", "24:00", "00:02" ] ), 2, "24:00");
+ is( shortestTime( [ "23:55", "24:00", "00:07" ] ), 5, "24:00 again");
+
+ done_testing;
+}
+