人間はそれを行うことができますか?
ファーサイドバッグ
ファーサイドバッグ
ファーサイドバッグ
ファーサイドバッグ
辞書を使用する必要があるだけでなく、統計的アプローチを使用して最も可能性の高いものを特定する必要がある場合があります (または、神が禁じているように、選択した人間の言語の実際の HMM を使用することもできます...)。
役に立つかもしれない統計を行う方法については、Peter Norvig 博士を参照してください。彼は、21 行のコードでスペル チェックに関する別の、しかし関連する問題に取り組んでいます:
http://norvig.com/spell-correct.html
(彼は、すべての for ループを 1 行に折りたたむことで少しごまかしていますが、それでもなお)。
更新これが頭に詰まったので、今日出産しなければなりませんでした。このコードは、Robert Gamble によって説明されたものと同様の分割を行いますが、提供された辞書ファイル内の単語の頻度に基づいて結果を並べ替えます (これは、ドメインまたは一般的な英語を表すテキストであると予想されます。上のリンクにある Norvig の .txt に辞書を追加して、欠落している単語をカバーしています)。
頻度の差が非常に大きい場合を除き、ほとんどの場合、2 つの単語の組み合わせは 3 つの単語の組み合わせよりも優れています。
このコードにいくつかの小さな変更を加えてブログに投稿しました
http://squarecog.wordpress.com/2008/10/19/splitting-words-joined-into-a-single-string/
また、このコードのアンダーフロー バグについて少し書きました..それを修正しますが、これは以前にログのトリックを見たことがない一部の人々を助けるかもしれないと考えました
:
あなたの言葉に加えて、私自身の言葉をいくつか出力してください -- 「orcore」で何が起こるかに注目してください。
perl splitwords.pl big.txt 単語
回答: 2 つの可能性
-子牛に答える
- 答えてください
ウィキッドウェザー: 4 つの可能性
- 悪天候
- 邪悪な私たちは彼女に
- 邪悪な天気
- 私たちは彼女に悪口を言いました
リキッドウェザー: 6 つの可能性
- 液体の天気
- 液体私たちは彼女に
- 天気予報
-彼女に私たちを怒らせた
- 液体の天気
- 私たちは彼女に会いました
driveourtrucks: 1 つの可能性
- トラックを運転する
gocompact: 1 つの可能性
- コンパクトに
スリムプロジェクター: 2 つの可能性
- スリムプロジェクター
- スリムなプロジェクトまたは
orcore: 3 つの可能性
- またはコア
- またはコア
- オーク鉱石
コード:
#!/usr/bin/env perl
use strict;
use warnings;
sub find_matches($);
sub find_matches_rec($\@\@);
sub find_word_seq_score(@);
sub get_word_stats($);
sub print_results($@);
sub Usage();
our(%DICT,$TOTAL);
{
my( $dict_file, $word_file ) = @ARGV;
($dict_file && $word_file) or die(Usage);
{
my $DICT;
($DICT, $TOTAL) = get_word_stats($dict_file);
%DICT = %$DICT;
}
{
open( my $WORDS, '<', $word_file ) or die "unable to open $word_file\n";
foreach my $word (<$WORDS>) {
chomp $word;
my $arr = find_matches($word);
local $_;
# Schwartzian Transform
my @sorted_arr =
map { $_->[0] }
sort { $b->[1] <=> $a->[1] }
map {
[ $_, find_word_seq_score(@$_) ]
}
@$arr;
print_results( $word, @sorted_arr );
}
close $WORDS;
}
}
sub find_matches($){
my( $string ) = @_;
my @found_parses;
my @words;
find_matches_rec( $string, @words, @found_parses );
return @found_parses if wantarray;
return \@found_parses;
}
sub find_matches_rec($\@\@){
my( $string, $words_sofar, $found_parses ) = @_;
my $length = length $string;
unless( $length ){
push @$found_parses, $words_sofar;
return @$found_parses if wantarray;
return $found_parses;
}
foreach my $i ( 2..$length ){
my $prefix = substr($string, 0, $i);
my $suffix = substr($string, $i, $length-$i);
if( exists $DICT{$prefix} ){
my @words = ( @$words_sofar, $prefix );
find_matches_rec( $suffix, @words, @$found_parses );
}
}
return @$found_parses if wantarray;
return $found_parses;
}
## Just a simple joint probability
## assumes independence between words, which is obviously untrue
## that's why this is broken out -- feel free to add better brains
sub find_word_seq_score(@){
my( @words ) = @_;
local $_;
my $score = 1;
foreach ( @words ){
$score = $score * $DICT{$_} / $TOTAL;
}
return $score;
}
sub get_word_stats($){
my ($filename) = @_;
open(my $DICT, '<', $filename) or die "unable to open $filename\n";
local $/= undef;
local $_;
my %dict;
my $total = 0;
while ( <$DICT> ){
foreach ( split(/\b/, $_) ) {
$dict{$_} += 1;
$total++;
}
}
close $DICT;
return (\%dict, $total);
}
sub print_results($@){
#( 'word', [qw'test one'], [qw'test two'], ... )
my ($word, @combos) = @_;
local $_;
my $possible = scalar @combos;
print "$word: $possible possibilities\n";
foreach (@combos) {
print ' - ', join(' ', @$_), "\n";
}
print "\n";
}
sub Usage(){
return "$0 /path/to/dictionary /path/to/your_words";
}