Re: Perl 'Expert' Quiz-of-the-Week #22 - Long ladders

Daniel Martin <martin-+m399P62/[email protected]>
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
You know, I don't think that anyone has mentioned in this discussion
that pragdave (http://pragprog.com/pragdave/) had this problem as one
of his "Code Katas" several months ago.  I admit that my perl solution
was based on a ruby solution I'd written up in response to that kata.
(Which can be found at http://snowplow.org/martin/katas/kata19.rb )

"Jurgen Pletinckx" <[email protected]> writes:

> I played around a bit more with BFS. Here are 
> some of the longest ladders - might come in 
> handy for timings, stress tests and compari-
> sons. (Of course, I should have mailed these 
> last week to be actually useful.)

If you care for independent confirmation, I got the same ladder
lengths for the same length words.

> Webster2
>
> 17 steps: idol -> upas
Also: obol -> upas

> 37 steps: alure -> yasht
This is the only one this long

> 54 steps: peltry -> zounds
This is the only one this long

> 40 steps: cortina -> turjite
Also: cortina -> turfite

> 37 steps: deadness -> thusness
Also: deafness -> thusness

> (for longer word lengths, the ladders become very 
> boring indeed. indefectibly -> undelectably ?)
They get really boring around length 20.

> words
>
> 20 steps: inca -> ursa
Also: usra -> veto  (but inca->veto is a simple 8 steps)

> 47 steps: agway -> troop
The only one for length 5, though in "words" the 
6 letter ladders were interesting:

 dobbin -> doodle, dobbin -> noodle, dobbin -> poodle,
 dobbin -> tootle, doodle -> robbin, noodle -> robbin,
 poodle -> robbin, robbin -> tootle

all at 25 words each.

> wordnet
>
> 34 steps: array -> rosid
Also: array -> devon, array -> demob, array -> lemon, 
      array -> robin and array -> eosin
> 47 steps: limply -> trusty
The only one for this length.

Here's the unrefined code that computes this; it takes an argument
that is the word length and then reads the dictionary through <> (so
redirect in the dictionary, or put several on the command line to use
the union)

#! /usr/bin/perl -w

use Time::HiRes qw(time);
use strict;
use vars qw(%maxPossible $len %words);

my $start = time;
$len = shift;

my %sig2words=();
while (<>) {
  chomp;
  next unless length==$len;
  next unless /^[a-z]+$/;
  my $w=lc; # use my $w=$_; for case-sensitive
  my @sigs=map {$a=$w; substr($a,$_,1)='_';$a;} (0..$len-1);
  for my $sig (@sigs) {
    $sig2words{$sig} ||= [];
    push @{$sig2words{$sig}}, $w;
  }
}

my ($sig, $words);
%words = ();
while (($sig,$words) = each %sig2words) {
  for my $word (@$words) {
    $words{$word} ||= [];
    push @{$words{$word}}, grep($_ ne $word, @$words);
  }
}

# printf STDERR "Loaded Dictionary, \%f seconds\n", time() - $start;

%maxPossible = ();

my $longestpath='unknown';
my $longestlen=-1;

for my $startword (sort keys %words) {
  next if ($maxPossible{$startword} and $longestlen > $maxPossible{$startword});
  my @q = ($startword);
  my %seen = ($startword => 0);
  my $step = 0;
  my @longest;
  while (@q) {
    $step++;
    my @qnext = ();
    for my $w (@q) {
      for my $nw (@{$words{$w}}) {
        next if defined($seen{$nw});
        $seen{$nw} = $step;
        push @qnext, $nw;
      }
    }
    @longest = @q if (!@qnext);
    @q = @qnext;
  }
  $step--;
  if ($step > $longestlen) {
    $longestlen = $step;
    $longestpath = join(", ",
                        map {"$startword -> $_"}
                        grep($_ ge $startword, @longest));
  } elsif ($step == $longestlen) {
    $longestpath = join(", ", $longestpath,
                        map {"$startword -> $_"}
                        grep($_ ge $startword, @longest));
  }
  for my $seen (keys %seen) {
    if (!$maxPossible{$seen} or $maxPossible{$seen} > $step + $seen{$seen}) {
      $maxPossible{$seen} =  $step + $seen{$seen};
    }
  }
}

print "longest is $longestpath at $longestlen steps\n";

# printf STDERR "Total \%f seconds\n", time() - $start;

__END__
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.