Box Relatives

Thoughts about puzzles, math, coding, and miscellaneous

NPR Puzzle for 2013-09-01: a perl solution

| 2 Comments

Here’s this past week’s NPR puzzle:

Think of a well-known celebrity who goes by a single name — the last two letters of which are alphabetically separated by only one letter (like A and C, or B and D). Replace this pair of letters with the one that separates them, and you’ll have a common, everyday word. What is it?

It used to be that a puzzle like this was tough to solve with a computer program, because there wasn’t a list of famous names available anywhere. Well, now there is such a list, and it makes solving things like this a snap. You will still need a list of common words to solve this puzzle, but those are available all over. I used the Enable dictionary from the NPL.

A few interesting quirks happened along the way to solving this puzzle. First, it turns out that this particular person isn’t listed in Wikipedia by only his/her first name. So I had to tweak the code a bit to look at all possible first names in my list. This created a bit of a logjam because ROBERT -> ROBES comes up a ton. So the final hacked code to give the answer is below. Not my best work, but not bad for ten minutes.

It’s also a relief to see that the intended answer had a score of 100. YAY FAMOUS PEOPLE LIST

#!/usr/bin/perl -w

use strict;

my $USAGE = "Usage: $0 NAME_FILE WORDLIST_FILE";

my $name_file = $ARGV[0] or die $USAGE;
my $word_list_file = $ARGV[1] or die $USAGE;

my %names;
open FILE1, $name_file or die $!;
while (<FILE1>)
{
	chomp;
	# Everything uppercase for consistency
	my $name = uc $_;
	my $score = 100;
	# Take out names with spaces
	#next if $name =~ / /;
	if ($name =~ /^(.*)\t(\d+)$/) {$name = $1;$score = $2;}
	$names{$name} = $score;
}
close FILE1;

my %words;
open FILE2, $word_list_file or die $!;
while (<FILE2>)
{
	chomp;
	$words{uc $_} = 1;
}
close FILE2;

# Go through names to find a match
my %used;
while (my ($name, $score) = each(%names))
{
	my $first; my $second;
	if ($name =~ /^(.*?) /) {$name = $1;}
	if ($name =~ /^(.*)(..)$/)
	{
		$first = $1;
		$second = $2;
	}
	next unless $second;
	#print "$name $first $second\n";
	my $num = ord(substr($second,0,1));
	if (ord(substr($second,1,1)) == $num + 2)
	{
		my $let = chr($num + 1);
		my $word = $first . $let;
		if ($words{$word} && !$used{$name})
		{
			print "$score\t$name\t$word\n";
			$used{$name} = 1;
		}
	}
}

2 Comments

Leave a Reply

Required fields are marked *.


This site uses Akismet to reduce spam. Learn how your comment data is processed.