- ベストアンサー
手直し依頼:n-gramのプログラミングで「可愛い」「あの子」「デートしたい」を結果に出力できない
- プログラミング歴3週間の私が作成したn-gramのプログラムが上手く動かないです。結果が「可愛い」「あの子」「デートしたい」になるように修正をお願いしたいです。
- n-gramのプログラムを作成しましたが、結果が「可愛い」「あの子」「デートしたい」とならず、どなたか優秀な方に手直しのお願いをしたいです。
- 私はプログラミング歴が3週間ですが、n-gramのプログラムを作成しました。しかし、結果が「可愛い」「あの子」「デートしたい」となりません。手直しをお願いしたいです。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> 新たに作ってみたのですが、「あひる」までは拾ってくれるのですが、 > 「すき」を拾ってくれません。どなたか手直しお願いいたします。 #1の回答のスクリプトで得たい答えは求められるのに、 なぜわざわざ作り直した挙句に直してくれとか おねだりするんですか? n-gramも使ってないですよね? #!/usr/bin/perl use strict; use warnings; use strict; my $DEBUG=1; my $str1 = "あひるがすき"; my $str2 = "あひるはすき"; #my $str1 = "可愛いあの子とデートがしたい"; #my $str2 = "あの子可愛いよね。デートがしたい"; my $len1 = length $str1; my $len2 = length $str2; my @words; for (my $i=0; $i<$len1; $i+=2) { print "\$i=$i\n" if $DEBUG; my $try_len = 2; my $common = ""; while ($try_len <= $len2 - $i) { my $try = substr $str1, $i, $try_len; my $pos = index $str2, $try; print "\$try=$try, $pos\n" if $DEBUG; if ($pos<0) { print "break inner loop\n" if $DEBUG; last; } $common = $try; $try_len += 2; } if ($common ne '') { $i+=length($common)-2; push @words, $common; } } print join(':', @words);
その他の回答 (4)
- sakusaker7
- ベストアンサー率62% (800/1280)
n-gramにずいぶんとご執心ですけど、結局のところなにがやりたいのでしょうか? 今回の例題から推測して、二つの文章を比較してできるだけ長い共通部分を 切り出すことが目的とも思えますが、だとすればそれのために n-gramを使うことはあまり適当ではないと思います。 Longest Common Sequence を求めるアルゴリズムを応用するとかしたほうが 効率がよいと思います。 文書比較アルゴリズム http://hp.vector.co.jp/authors/VA007799/viviProg/doc5.htm Longest common subsequence problem - Wikipedia, the free encyclopedia http://en.wikipedia.org/wiki/Longest_common_subsequence_problem n-gramそのものの資料のポインタはもう一つの質問の方で 書きましたのでこちらでは省略します。
補足
新たに作ってみたのですが、「あひる」までは拾ってくれるのですが、 「すき」を拾ってくれません。どなたか手直しお願いいたします。 my $a = "あひるがすき"; my $b = "あひるはすき"; my $len1 = length($a); my $len2 = length($b); my $i = 0; my $j = 0; while($len1 >= $i) { while($len2 >= $j) { print $i; print $j; if(0 == $i % 2) { if(0 == $j % 2) { my $word1 = substr($a, $i, $j + 2); my $word2 = substr($b, $i, $j + 2); if($word1 eq $word2) { my $len3 = length($word1); my $nextword=substr($word1, $even1, $len3); push(@lastwords, $nextword); } } } $j++; } $i++; } print $popwords = pop(@lastwords);
- sakusaker7
- ベストアンサー率62% (800/1280)
希望の結果は得られているようですけど、n-gramを使ってないのですが それはいいんでしょうか?
お礼
P.S.本でも可です。よろしくお願いいたします。
補足
実はn-gramなるものを良く理解していないので、もし良いサイトがあったらご紹介よろしくお願いいたします。とりあえず、これでいきます。。
- moon_night
- ベストアンサー率32% (598/1831)
追記。 my $a = "可愛いあの子とデートがしたい"; my $b = "あの子可愛いよね。デートがしたい"; とある場合、 $aの一文字目からHITがあるか調べていきます。 HITしたら、続いて二文字目もヒットがあるか調べます。 HITしたところまでの文字を取得して次の文字から調べます。 例) $bの中に$aの一文字目の「可」があるか調べる。 HITするので、$bの中に「可愛」がHITするか調べる。 HITするので、$bの中に「可愛い」」がHITするか調べる。 HITするので、$bの中に「可愛いあ」がHITするか調べる。 HITしないので、「可愛い」の文字を取得して、次の「あ」を調べることをする。 以下文字がなくなるまで上の繰り返し。
お礼
よく分かりました。自分なりにまた作ってみたいと思います。ありがとうございました。
- moon_night
- ベストアンサー率32% (598/1831)
少し意味がわかりません(定義が曖昧です)が、 >結果が「可愛い」「あの子」「デートしたい」 という結果が満たせればいいだけならば以下。 ご質問のプログラムは文字単位でしか調べてないので、単語単位ではHITしません。 my $a = "可愛いあの子とデートがしたい"; my $b = "あの子可愛いよね。デートがしたい"; $len1 = length($a); $len2 = length($b); my $i = 0; while($i < $len1) { my $j = 0; while(&tx($b,substr($a, $i, $j+2))>=0 and &tx($b,substr($a, $i, $j+2))+$j < $len2) { $j+=2; } if ($j) { push(@word, substr($a, $i, $j)); $i += $j; } else { $i += 2; } } sub tx { return index($_[0],$_[1]); } print join(',', @word);
お礼
見てもさっぱり分かりませんが、ご名答です。もっと勉強がんばります。ありがとうございました。もしアルゴリズムのご説明もいただけるようでしたら、お願いいたします。
お礼
これがn-gramなのですね。ありがとうございました。
補足
自分でも努力すべきだと思ったからです。