Weekly Challenge 206
Tags: perl, python, theweeklychallenge
Published: 2023-02-27 12:52:46

[Challenge](https://theweeklychallenge.org/blog/perl-weekly-challenge-206/), [My solutions](https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-206/sgreen)

Two relatively straight forward tasks this week, so without further ado, here's my blog post.

## Task 1: Shortest Time

### Task

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.

### My solution

The first thing I do is set the `shortest` value to 1440 minutes (being 24 hours). We know that at least one solution is going to be shorter than that.

I then convert the input list `times` to a new list called `minutes`, representing the minutes since midnight. As we use a 24 hour clock, it's as simple as multiplying the hours by 60 and adding the minutes. Although the task doesn't specifically mention it - as it's not attached to a date - I assume we don't need to worry about changing clocks for daylight savings time.

The next thing is to obtain the list of pairs. While I could have used combinations from itertools, since it's just a pair I use two loops. The outer loop is between 0 and two less than the length of the `minutes` list. The inner loop is from 1 more than the outer loop to the end of the list.

I calculate the `diff` value by subtracting the two minutes between the the applicable items from the `minutes` list. As we don't care about which is first, I use the absolute value. However, if the difference is more than twelve hours we know the shorter time occurs if we span midnight. For example the difference between 12:05am and 11:55pm is 1430 minutes, where as the time between 11:55pm and 12:05am the next day is only 10 minutes.

For each iteration, if the `diff` value is less than `shortest`, I set the new `shortest` value. Finally, I print the `shortest` value.

### Examples

```bash
$ ./ch-1.py 00:00 23:55 20:00
5

$ ./ch-1.py 01:01 00:50 00:57
4

$ ./ch-1.py 10:10 09:30 09:00 09:55
15
```

## Task 2: Array Pairings

### Task

You are given an array of integers having even number of elements.

Write a script to find the maximum sum of the minimum of each pairs.

### My solution

Mohammad's e-mails usually arrive in my inbox in the late afternoon in my timezone (AEDT, UTC+1100). Before I write my solutions, I read the task on the bus home or before dinner if I didn't take the bus. Between then and when I actually code the solution, I think about the best way to solve it.

My original thoughts were a complicated solution that involved a recursive function and the [combinations](https://docs.python.org/3/library/itertools.html#itertools.combinations) function from itertools. I didn't like that approach at all.

After some drawings on my whiteboard, it dawned on me that if we ordered the numbers, the solution will always be the odd positioned values in that list (i.e. 1st, 3rd, 5th, 7th, etc). The reason for this is that if we paired the ordered numbers the first value will be the minimums that give us the greatest maximum. Because we start indexes at zero, odd positioned values are evened indexed, i.e. `n[0]`, `n[2]`, `n[4]`, etc.

This then became an easy task to code. For Python, we can use `sum(n[::2])` to get a sum of the even indexed values. Perl doesn't have an equivalent of stepping by two, but thankfully the (pairkeys)[https://metacpan.org/pod/List::Util#pairkeys] function from List::Util achieves the same thing.
### Examples

```bash
$ ./ch-2.py 1 2 3 4
4

$ ./ch-2.py 0 2 1 3
2
```

### Single line solutions

It is of course possible to do this in a single line script, in both Python and Perl. However, the readability of the code is gone with this approach.

```bash
$ python3 -c 'import sys; print(sum(sorted(int(i) for i in sys.argv[1:])[::2]))' 1 4 2 3
4

$ perl -E 'use List::Util qw(pairkeys sum); say sum(pairkeys(sort { $a <=> $b } @ARGV))' 1 4 2 3
4
```