如何搜索按字母顺序排列的六个字母的单词



我最近创建了一个Perl脚本,它用下面的代码搜索以D和E开头的单词:

$infile = 'words.txt';
open(IN, $infile);
$count = 0;
while ($word = <IN>) {
chomp($word);
if ($word =~ /^dw*e$/i) {
    print "$wordn";
    $count++;
  }
}
print "$countn";

我最近决定分叉代码并创建一个脚本来搜索一个由六个字母组成的单词,并且单词中的字母按字母顺序(A 到 Z(排列。我计划不使用单词.txt,而是使用位于usr/share/dict/words的Unix标准字典。如何通过修改此代码来实现此目的?

看起来您真正需要的是一种算法,用于检查给定单词中的字母是否按字母顺序排列。有几种方法,但此子例程的工作原理是将单词拆分为其组成字符的列表,对该列表进行排序并重新组合它。如果结果与原始单词匹配,则该单词已排序。

use strict;
use warnings;
use feature 'fc';
for (qw/ a ab ba cab alt effort toffee /) {
  print "$_n" if in_alpha_order($_);
}
sub in_alpha_order {
  my $word = fc(shift);
  my $new = join '', sort $word =~ /./g;
  return $new eq $word;
}

输出

a
ab
alt
effort

如果你真的想在正则表达式中做到这一点,你可以构建一个替代,比如

a(?=[a-z]) | b(?=[b-z]) | c(?=[c-z]) ...

这是一个以这种方式工作的程序。它的输出与上面的输出相同。

use strict;
use warnings;
my $regex = join '|', map "${_}(?=[$_-z])", 'a'..'z';
$regex = qr/^(?:$regex)*.$/i;
for (qw/ a ab ba cab alt effort toffee /) {
  print "$_n" if $_ =~ $regex;
}

要支持非 ASCII 单词:

#!/usr/bin/perl
use strict;
use warnings;
use encoding 'utf8'; # Upgrade byte strings using UTF-8
use Unicode::Collate; # To sort letters alphabetically
use constant NCHARS => 6; # Consider only words with NCHARS characters in them
my $filename = '/usr/share/dict/words';
open (my $fh, '<:encoding(UTF-8)', $filename)
    or die "can't open '$filename' $!";
my $collator = Unicode::Collate::->new();
while (my $word = <$fh>) {
    chomp $word;
    my @chars = ($word =~ /X/g); # Split word into characters
    # Print words with given length that have characters in alphabetical order
    print "$wordn" if (@chars == NCHARS &&
                        join('', $collator->sort(@chars)) eq $word);
}
close $fh;

这里有一个选项:

#!/usr/bin/env perl
use warnings;
use strict;
my $wordsFile = '/usr/share/dict/words';
my $count     = 0;
open my $fh, '<', $wordsFile or die $!;
while ( my $word = <$fh> ) {
    chomp $word;
    next unless length $word == 6;
    my $sorted = join '', sort split //, lc $word;
    if ( $sorted eq lc $word ) {
        print "$wordn";
        $count++;
    }
}
close $fh;
print "$countn";

这是按字母顺序排列字母split原始单词。 这些字母被重新join以形成一个新单词。 然后与原始单词进行比较。 如果它们相同,则将其打印并计数。

我有一个类似于Kenosis和Borodin的解决方案,但是您需要小心大小写。 Perl 的默认排序函数将所有大写字母放在小写字母之前。 我下面的版本可以解决这个问题。

#!/usr/bin/env perl
use strict;
use warnings;
sub is_six_letter_word {
    my $word = shift;
    return length($word) == 6;
}
sub is_letters_in_alphabetical_order {
    my $word = shift;
    $word = fc($word);
    my @chars = split("", $word);
    my $sorted_word = join("", sort(@chars));
    return $word eq $sorted_word;
}
open(my $fh_in, $ARGV[0]) or die "Error opening input file";
my $word = undef;
while ($word = <$fh_in>) {
    chomp($word);
    if (is_six_letter_word($word) && is_letters_in_alphabetical_order($word)) {
        printf("%sn", $word);
    }
}
close($fh_in);

最新更新