3

私は最近、次のコードでDとEで始まる単語を検索するPerlスクリプトを作成しました。

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

私は最近、コードをフォークして、6文字の単語を検索し、その単語の文字がアルファベット(AからZ)の順序であるスクリプトを作成することにしました。words.txtを使用する代わりに、 usr / share / dict/wordsにあるUnix標準辞書を使用する予定です。このコードを変更してこれを達成するにはどうすればよいですか?

4

4 に答える 4

9

本当に必要なのは、特定の単語の文字がアルファベット順であるかどうかをチェックするためのアルゴリズムのようです。いくつかの方法がありますが、このサブルーチンは、単語をその構成文字のリストに分割し、そのリストをソートして再結合することによって機能します。結果が元の単語と一致する場合、その単語はすでに並べ替えられています。

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;
}
于 2013-01-07T02:28:47.270 に答える
2

非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 "$word\n" if (@chars == NCHARS &&
                        join('', $collator->sort(@chars)) eq $word);
}
close $fh;
于 2013-01-07T03:54:52.360 に答える
1

1つのオプションがあります:

#!/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 "$word\n";
        $count++;
    }
}

close $fh;

print "$count\n";

これsplitは、文字をアルファベット順に並べる元の単語です。文字はjoin新しい単語を形成するためにリードされています。次に、元の単語と比較されます。それらが同じである場合、それは印刷されてカウントされます。

于 2013-01-07T02:34:44.077 に答える
1

私はケノーシスやボロディンに似た解決策を持っていますが、ケースに注意する必要があります。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("%s\n", $word);
    }
}

close($fh_in);
于 2013-01-07T02:51:34.480 に答える