Ieronim,
I am glad you learned something from my code. It was intended to be concise while also being straight forward.
DBM::Deep is not
currently designed to be fast as it is written in pure perl. If you want speed - try the version below which uses
Storable. I believe it outperforms yours though I have not
Benchmarked it.
I admit that I have not had a chance to disect your code but I am interested in how you build bridges for words not in the dictionary. If it is only the endpoints, then modifying my code to do the same would be trivial. I am going to spend some time disecting your code and may update the version below if all you are handling is end-points.
#!/usr/bin/perl
use strict;
use warnings;
use Storable;
use Text::LevenshteinXS 'distance';
my $db = -e 'dictionary.db' ? retrieve('dictionary.db') : build_db();
my ($src, $tgt) = @ARGV;
# Error handle defined, length, exist in $db and distance() > 1
my $len = length($tgt);
my $list = $db->{$len};
my $path = find_path($src, $tgt, $list);
print "$path\n";
sub find_path {
my ($src, $tgt, $list, $seen, $work) = @_;
@$work = map {key => $_ => path => "$src->$_"}, @{$list->{$src}} i
+f ! defined $work;
my $next = [];
for (@$work) {
my ($word, $path) = @{$_}{qw/key path/};
next if $seen->{$word}++;
return $path if $word eq $tgt;
push @$next, map {key => $_, path => "$path->$_"}, @{$list->{$
+word}};
}
return find_path($src, $tgt, $list, $seen, $next) if @$next;
return 'path not found';
}
# Runs once and can be removed after DB is built
sub build_db {
open (my $dict, '<', '2of12.txt') or die "Unable to open '2of12.tx
+t' for reading: $!";
my ($db, %data);
while (<$dict>) {
chomp;
push @{$data{length()}}, $_;
}
for my $len (keys %data) {
my $end = $#{$data{$len}};
for my $i (0 .. $end - 1) {
my $word = $data{$len}[$i];
for my $j ($i + 1 .. $end) {
my $test = $data{$len}[$j];
if (distance($word, $test) == 1) {
push @{$db->{$len}{$word}}, $test;
push @{$db->{$len}{$test}}, $word;
}
}
}
}
store $db, 'dictionary.db';
return retrieve('dictionary.db');
}