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

  1. Sweet. And huzzah for your excellent FamousNames.txt!

    (And hooray that her name didn’t have an accent in the word list!)

    • Yes! Thank you for noticing that. The Wikipedia list (from which the famous names are derived) were made with crosswords in mind, so it made sense to ditch the accents. Still, it took a fair amount of time to make sure something like Goran Ivanišević came out properly.

Leave a Reply

Required fields are marked *.


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