Monday, January 28, 2013

Word games, part two

Sometimes I wake up in the morning, and manage to get back to sleep. Other times, my brain starts ticking over, and there's no point shouting at it to go back to sleep. This morning was an example of the latter.

Specifically, I started trying to work out the nine-letter word from the Sunday Age, from memory. From there, I started thinking about this earlier bit of hackery, and how I really should have tried to solve the problem properly. So I came up with this:

#!/usr/bin/perl

my $DICT="/etc/dictionaries-common/words";
my $WORD=shift();

my $LC_WORD=lc($WORD);
my $SORTED_WORD=(join '', sort { $a cmp $b } split(//, $LC_WORD));
my $LENGTH=length($SORTED_WORD);

open FILE, $DICT or die $!;

while(<FILE>) {
        chomp;
        $CANDIDATE=(join '', sort { $a cmp $b } split(//, lc($_) ));
        next if (length($CANDIDATE) ne $LENGTH);
        print ("FOUND: $_\n") if($CANDIDATE eq $SORTED_WORD);
}

close FILE;
exit 0;


Perl is definitely not my favourite language (too many magic variables for my liking!) but it's quick, and it works.

Of course, plenty of other people have already solved this issue (and gone well beyond too, in this case) but that's not the point - it was an interesting exercise. My wife did ask "isn't that cheating?" but I kinda think if you write a program to solve the problem, it's arguable not really cheating. Right?

6 comments:

  1. Perl is not easy to read.

    So what was wrong with my

    grep ^[the9characters][the9characters][the9characters][the9characters][the9characters][the9characters][the9characters][the9characters][the9characters]$ /usr/share/dict/words solution?

    ReplyDelete
    Replies
    1. Ummm... well, it doesn't work for multiple occurrences of one (or more) letter in either the letter sequence or the candidate match.

      Take for example these nine letters: toepmerde (yesterday's puzzle). The multiple greps will incorrectly match preempted, reordered and torpedoed, which cannot be made from those nine letters. It's only by ordering the letters in the original string and the candidate in a fixed way (I chose an ascending alphabetical order, but you could really choose any, so long as you were consistent) that this will give correct results. Well, there would be other ways, I suppose, such as constructing a set and doing a set-wise comparison, but I digress...

      I was also going to say that the Perl version ought to give better performance, but some test runs show that your grep version is actually faster! Oh well. Grep must have some serious optimisations in it.

      Delete
    2. But I agree, Perl isn't pleasant to read.

      Delete
  2. Yeah, but it's close enough and you can work out the answer,
    and you dont have to write any silly perl.

    Am sure you can do more fancy regexps to reduce the qualifying answers
    to the one true answer.

    ReplyDelete
  3. You had to write this, didn't you.

    I'm sitting here banging my head against the wall trying to figure out how to add version 5 UUID's to an ldap directory of users so the macs (via netatalk) can correctly parse acl's and here I find a fun perl and grep exercise.

    I'm never going to figure out my LDAP answer now.

    Thanks. :)

    ReplyDelete
    Replies
    1. My pleasure, Lance. There's no limit to what you can achieve, so long as it's not what you're supposed to be working on :-)

      Delete