我正在研究一个单词链程序,并给出了两个单词和一个单词文件,程序通过一次只更改一个字母,从一个单词更改为另一个单词,找到如何从一个单词转到另一个单词关闭文件中的文字。
我正在研究一个子程序,该子程序将返回文件中只有一个字母不同的单词列表。
我知道我可能会使用正则表达式来查找单词并将其添加到列表中。感谢有人给予的任何帮助。
#!/usr/bin/perl -w
$start_word = $ARGV[0];
$end_word = $ARGV[1];
my $file = "wordlist.txt";
open (FH, "< $file" ) or die "Can't open $file for read: $!";
my @lines;
while(<FH>)
{
push (@lines, $_);
}
#print @lines;
#find word diff
#return list of words with 1 letter diff
#recursion to return smallest stack
答案 0 :(得分:1)
可以轻松优化您的候选人群:链中所有可能的单词必须具有相同的长度。
sub read_all_candidates {
my($dict,$start) = @_;
open my $fh, "<", $dict or die "$0: open $dict: $!\n";
my @pool;
while (<$fh>) {
chomp;
next if length($_) != length($start) || $_ eq $start;
push @pool, lc $_;
}
\@pool;
}
考虑到链中单词的长度,您还可以为该长度的单词构建专门的Regexp
实例。
# Computes and caches a Regexp object (created with qr//) that
# matches pairs of one-hop words concatenated one after the
# other (e.g., "doghog" for dog and hog). For example, words of
# length 3 would generate the following pattern:
#
# ^(.)(.)(.)(?:.\2\3|\1.\3|\1\2.)$
#
# You need only call this sub once per run.
my $_one_hopper;
sub _compute_one_hopper {
my($length) = @_;
my $pattern = "^" . "(.)" x $length;
my @choices;
foreach my $n (1 .. $length) {
push @choices => join "", map $_ == $n ? "." : "\\$_", 1 .. $length;
}
#print $pattern, "\n";
$pattern .= "(?:" . join("|" => @choices) . ")\$";
eval "\$_one_hopper = qr/$pattern/" or die "$0: internal error";
}
在
中使用$_one_hopper
# Returns one-hop neighbors of $from taken from @$words but that are
# not present in %$seen.
sub one_hop {
my($from,$words,$seen) = @_;
$_one_hopper = _compute_one_hopper length $from
unless defined $_one_hopper;
grep !$seen->{$_} && "$from$_" =~ /$_one_hopper/, @$words;
}
将所有内容捆绑在一起,您的主循环具有以下结构。
my $words = read_all_candidates $dict, $start;
my $min = 1; # minimum number of transitions from $start to
my $seen = {}; # words seen in earlier batches (prevents
my @last = ($start); # last batch of neighbors
while (@last) {
my @next;
foreach my $word (@last) {
my @onemore = one_hop $word, $words, $seen;
++$seen->{$_} for @onemore;
...
}
}