Perl Weekly Challenge #014 is out!

I worked on these last night while watching John Oliver, and now I blog!

## Challenge 1

As always with the number play challenges, I have to read carefully and, if possible, get the expected answer for checking.

Let a0 = 0. Then, for n ≥ 0, if there exists an m < n such that am = an, take the largest such m and set an+1 = n − m; otherwise an+1 = 0.

There, that makes sense. Kinda. I just ran it on a series of numbers, rather than make a subroutine out if it. And, it seems, the best way to get `van_eck(40)` is to loop and get `van_eck(0)` and `(1)` and so on. This does not naturally give itself over to a recursive solution.

Looking back, it seems like the better way (which is more O(n) and less O(nlogn)), would be to reverse the `0..\$n-1` range and `last` on the first one, rather than cover all of the range to find the highest, and if this was real and working on much higher numbers, I’d go there. But I was playing with `next` and `last` in the other challenge, so I left it.

``````#!/usr/bin/env perl

use strict ;
use warnings ;
use feature qw{ postderef say signatures state } ;
no warnings qw{ experimental::postderef experimental::signatures } ;

use Carp;

# Write a script to generate Van Eck’s sequence starts with 0.
# This challenge was proposed by team member Andrezgz.

# 0, 0, 1, 0, 2, 0, 2, 2, 1, 6, 0, 5, 0, 2, 6, 5, 4, 0, 5 ... [1]

# let a[0] = 0
my @a ;
push @a , 0;

for my \$n ( 0 .. 30 ) {

# otherwise a[n+1]=0
\$a[\$n+1] = 0;

# for n >= 0, if there exists an m < n such that a[m] == a[n],
# take the largest such m and set a[n+1] = n-m,
for my \$m ( 0 .. \$n -1 ) {
\$a[\$n+1] = \$n - \$m if \$a[\$n]==\$a[\$m];
}
say qq{n = \$n \t a[n] = \$a[\$n]};
}

__DATA__

n = 0 	 a[n] = 0
n = 1 	 a[n] = 0
n = 2 	 a[n] = 1
n = 3 	 a[n] = 0
n = 4 	 a[n] = 2
n = 5 	 a[n] = 0
n = 6 	 a[n] = 2
n = 7 	 a[n] = 2
n = 8 	 a[n] = 1
n = 9 	 a[n] = 6
n = 10 	 a[n] = 0
n = 11 	 a[n] = 5
n = 12 	 a[n] = 0
n = 13 	 a[n] = 2
n = 14 	 a[n] = 6
n = 15 	 a[n] = 5
n = 16 	 a[n] = 4
n = 17 	 a[n] = 0
n = 18 	 a[n] = 5
n = 19 	 a[n] = 3
n = 20 	 a[n] = 0
n = 21 	 a[n] = 3
n = 22 	 a[n] = 2
n = 23 	 a[n] = 9
n = 24 	 a[n] = 0
n = 25 	 a[n] = 4
n = 26 	 a[n] = 9
n = 27 	 a[n] = 3
n = 28 	 a[n] = 6
n = 29 	 a[n] = 14
n = 30 	 a[n] = 0
``````

## Challenge 2

Using only the official postal (2-letter) abbreviations for the 50 U.S. states, write a script to find the longest English word you can spell? Here is the list of U.S. states abbreviations as per wikipedia page. This challenge was proposed by team member Neil Bowers.

Bring in the States!

``````    AL AK AZ AR CA CO CT DE FL GA
HI ID IL IN IA KS KY LA ME MD
MA MI MN MS MO MT NE NV NH NJ
NM NY NC ND OH OK OR PA RI SC
CD TN TX UT VT VA WA WV WI WY
``````

This time, instead of my traditional, curated, collected from password researchers list of words, I went with `/usr/share/dict/words`. I also went through some clever on first pass, then realized that `while` and `shift` are not as good as `for` and `last`.

For each word, first I split apart each word with `/\w{2}/g`, turning `"DEAL"` into `["DE","AL"]`, and then rejoined them, comparing the output with the input, to make sure I have something valid to work with. Double-duty, this also ensured that words with odd numbers of letters, like `"DEALS"` were never in play.

If you’re looking at `for (){ for () { next } }`, the assumption is that you’re breaking out of the inner loop only, so label the outer loop as `FOR` (because naming is not where I wanted to waste my creativity) and ran `next FOR` to make sure the word is skipped.

I half-considered having `\$longest` as a state variable, but no, I needed it outside so I just said the longest of the list.

When doing things like `\$states{\$wo} ? 1 : 0`, I do the ternary operator because otherwise I get `1` or `undef`, and that makes testing it a bit hairy. I suppose I should’ve put a defined or, but I’ve committed this code already, so eh.

``````#!/usr/bin/env perl

use feature qw{ say };
use strict;
use warnings;

# Using only the official postal (2-letter) abbreviations for the
# 50 U.S. states, write a script to find the longest English word
# you can spell? Here is the list of U.S. states abbreviations as
# Neil Bowers.

# using the %states hash makes for easy testing
my %states = map { \$_ => 1 } qw{
AL AK AZ AR CA CO CT DE FL GA
HI ID IL IN IA KS KY LA ME MD
MA MI MN MS MO MT NE NV NH NJ
NM NY NC ND OH OK OR PA RI SC
CD TN TX UT VT VA WA WV WI WY
};

# more universally available than my go-to dictionary DB
my @words;
if ( open my \$fh, '<', '/usr/share/dict/words' ) {
@words = map { chomp; uc \$_ } <\$fh>;
}

my \$longest = '';
FOR: for my \$word (@words) {
my @word = \$word =~ /(\w{2})/g;

# there are apostrophes and unicode in that list
# this ensures that what we're looking at is valid.
my \$join = join '', @word;
next unless \$join eq \$word;

# we check every letter pair and determine if it's in
# the states hash. we have labelled the outside for loop
# as FOR, so we can `next` on the outer loop, not just the
# inner loop.
for my \$wo ( @word ) {
my \$n = \$states{\$wo} ? 1 : 0;
next FOR unless \$n;
}

# words that are not entirely made out of state abbreviations
# will not reach this point. And this will ignore words of
# identical size to the found longest, but I know they don't
# exist.
\$longest = \$word if length \$longest < length \$word;
}
say \$longest;

__DATA__

CACOGALACTIA

noun In pathology, a bad condition of the milk.
``````

I don’t know it, and that definition sounds like a bad translation, but again, eh.

## Challenge 3?

Find the given city current time using the Geo DB Cities API. The API challenge is optional but we would love to see your solution.

It’s the API challenge. As much as I love `LWP` and `Mojo::UserAgent`, I think I’ll dig out of my post-TPCiP work pile before I think on it.

If you have any questions or comments, I would be glad to hear it. Ask me on Twitter or make an issue on my blog repo.