#!/usr/bin/perl use strict; use warnings; use DBM::Deep; use Text::LevenshteinXS 'distance'; my $db = DBM::Deep->new('dict.db'); build_db($db) if ! scalar keys %$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}} if ! 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'; } sub build_db { my $db = shift @_; open (my $dict, '<', '2of12.txt') or die "Unable to open '2of12.txt' for reading: $!"; my %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; } } } } }