Weekly Challenge 100
Tags: perl, perlweeklychallenge
Published: 2021-02-15 12:12:40

[Challenge 100](https://perlweeklychallenge.org/blog/perl-weekly-challenge-100/)

# TASK #1 › Fun Time

## The task

You are given a time (12 hour / 24 hour).

Write a script to convert the given time from 12 hour format to 24 hour format and vice versa.

Ideally we expect a one-liner.

## My solution

Let's start with the one liner.

```
($h,$m,$a)=($ARGV[0]=~/^(\d+):(\d+)\s*([ap]m)?$/);printf $a?("%02d:%02d",($h%12+($a eq"pm"?12:0)),$m):("%02d:%02d %s",($h%12)||12,$m,$h>=12?"pm":"am")
```
Yes, it works. But really doesn't explain what I'm doing in any great detail. So the solution I am submitting actual explains the above in more detail.

Now I'm sure when they figured out time many millennia ago computers were not even a pipe dream. This unfortunately make time a difficult thing to handle in the digital age.  Specifically, 12:00<b>p</b>m is one minute after 11:59<b>a</b>m. And [Internet time](https://en.wikipedia.org/wiki/Swatch_Internet_Time) never really took off thankfully.

For this task I read a string, and split it into an `$hour`, `$minute` and `$apm` (what is that part actually called?). I then check the $hour is valid (1-12 if am/pm specified, 0-23 if not).

It's then just a matter of showing the converted time. If we are going from 12 hours to 24 hours, the new hour is `$hour%12`, and we add 12 if the indicator is 'pm'. Going the other way, we set `$apm` to 'pm' if `$hour >= 12`. We then use `$hour%12`, and use 12 if the new hour is 0. In all cases, the minutes value remains unchanged.

One gotcha I had was `./ch-1.pl 12:40 pm` didn't give me the result I desired. This is because `@ARGV` is actually two values `12:40` and `pm`. Using `./ch-1.pl "12:40 pm"` fixes this (at least in bash).

## Examples

```
» ./ch-1.pl "5:15 pm"
17:15

» ./ch-1.pl "19:15"
07:15 pm
```

# TASK #2 › Triangle Sum

## The task

You are given triangle array.

Write a script to find the minimum path sum from top to bottom.

## My solution

Let's start with some fundamentals

* The smallest number in a choice doesn't lead the smallest sum. Take `[1], [1,2], [8,9,1]` as an example. In this case, choosing the 1 in the second row won't result in the smallest sum. Therefore we need to walk all paths.
* The number of possible paths is 2<sup>@rows - 1</sup>.
* As noted in the task, the x value remains the same if going to left, or x + 1 if going right.

The task can be broken down into three parts.

1. It's sometimes a challenge to parse the input correctly. For this task, I slurp up all the input, and use a regular expression to extract the numbers. One this is done, we know that the first row is contains one number, the second row two numbers, third row has three numbers, and so on.
1. I then walk each path, and find the lowest value. For this I have a counter `$i` from 0 to 2<sup>$#rows</sup>-1. For each iteration, we use binary arithmetic to determine if we will walk left or right. 
1. Once we have figured out the minimum path, we print the solution.

## Examples

```
» ./ch-2.pl "[ [1], [2,4], [6,4,9], [5,1,7,2] ]"
1 + 2 + 4 + 1 = 8

» ./ch-2.pl "[ [3], [3,1], [5,2,3], [4,3,1,3] ]"
3 + 1 + 2 + 1 = 7

```