映画のエンドロール観る派?観ない派?

perl初心者です。どうぞ助けて下さい。
以下のようにデータがならんでいる時、

pphhhppphhhppppppphhppppppppppppppppppphhh

pが連続した文字の連続数は
2、3、7、19
となります。

今、知りたいのはこのようなpの連続数の出現回数です。つまり、たとえばpが19回連続してあるものは何回でてきたか、が知りたいのです。
上の例だと1回が正解となります。
ところが、スクリプトを書くとき、
たとえば以下のようにしたとき、
pが19回なら重複カウントはなくても、
pを2でカウントしたら、
本当に出てきて欲しいこたえは一回なのに、
P=3、7、19のどれにも該当してしまいます。

#!/usr/bin/perl ;
open(IN, "text1.txt") or die ;

open(OUT, ">text1out.txt");

while(<IN>) {
chomp ;
if (/(\S+)/) {

$name = $1 ;

if ($name =~ /^ppppppppppppppppppp/) {
{$count++;}
;

}
print OUT "$count\n" ;
}
}
close (IN) ;
close (OUT) ;

正規表現の中を工夫すればいいのだと思いますが、


大変困っております。宜しくお願いします。

A 回答 (5件)

アバウトな実装ですが、こんなんとか:



> cat a.pl
$_ = 'pphhhppphhhppppppphhppppppppppppppppppphhh';
while ( s/^(.)\1*// ){ $char_map{$1}{ length( $& ) }++; }
foreach $c ( sort keys %char_map ){
%char_len_map = %{$char_map{ $c }};
foreach $n ( sort keys %char_len_map ){ print $c,' ', $n, ' ', $char_len_map{ $n }, "\n"; }
}

以下が実行結果:
> perl a.pl
h 2 1
h 3 3
p 19 1
p 2 1
p 3 1
p 7 1

ポイントは、tasekiさんがアドバイスしているように、「連続数が何個あるか」という問題を、
step.1)連続する文字列毎に切り出す。
step.2)切り出した文字列の、文字種と文字列長をカウントする。
という問題に分割して解決してるところ。

この回答への補足

感動しております。
本当に感謝です!
ただ、結果が多いので、コマンド画面上だと不便なので、
ファイルに出力したいと思い、
以下のように書いてみたのですが、
うまく出力できないのです。
朝からずっと考えていろいろ試しているのですが、
全くできません。
申し訳ありませんが、教えて頂けませんか?


#!/usr/local/bin/perl
$_ = 'pppppppuuuuuuuuuuuuuuuuuuuufffffffffffffffpppuuu';
open(LOG,">MOJICount.log");
while ( s/^(.)\1*// ){ $char_map{$1}{ length( $& ) }++; }
foreach $c ( sort keys %char_map ){
%char_len_map = %{$char_map{ $c }};
foreach $n ( sort keys %char_len_map ){print LOG "$c,' ', $n, ' ', $char_len_map{ $n }, \n";
close(LOG);}}

補足日時:2005/08/16 10:18
    • good
    • 0

> コマンド画面上だと不便なので、


> ファイルに出力したい

$check_char = 'p';

open(IN, './text1.txt') or die ;
$_ = <IN>;
close(IN);

foreach (split(/[^$check_char]+/)) { $len_list{(length)}++; }

open(LOG, '>./MOJICount.log') or die;
foreach (sort { $a <=> $b } keys %len_list) {
print LOG "$check_char が $_ 個連続している部分は $len_list{$_} ヶ所あります。\n";
}
close(LOG);
    • good
    • 0
この回答へのお礼

本当に助かりました。
御礼が遅くなり申し訳ございません。
ここで失礼致しますが、
みなさんの回答は本当に参考になり、
大変助かりました。
心より御礼を申し上げて、締め切りとさせて頂きます。

お礼日時:2005/09/21 12:27

19個のpを数える場合


-------------------
$_=<IN>;
$n= s/(^|[^p])p{19,19}(?!p)//g;
print $n;
    • good
    • 0
この回答へのお礼

御礼が遅くなり申し訳ございません。
有り難うございました!

お礼日時:2005/09/21 12:25

> つまり改行はありません。



ということは、whileループやchompは不要ですね。

open(IN, "text1.txt") or die ;
$all_data = <IN>;
close(IN);

で、全データを読み込めます。

> 重複なしにカウント

とおっしゃる意味は、たとえば「pppppp」の中には「ppp」が2つ含まれているので「pppが2個」とはカウントしない、という意味でしょうか。

目的の連続数の他はカウントしなくていいなら、ANo.1の方法よりもっと簡単です。配列に各連続数を保存しなくていいので、
たとえば、文字列から「ppppp」を削除、というのを繰り返して、何回繰り返したら無くなったのか?を数えれば良いと思います。
以下サンプルコードです。
--------------------
$text = 'pphhhppphhhppppppphhppppppppppppppppppphhh';

# $textの中に「'p'の7連続が何個あるか」が$resに入る
$res = &len_count($text, 'p', 7);
print $res;

sub len_count {
my($txt, $char, $len) = @_;
my $cnt = 0;
while ($txt =~ s/(?<!\Q$char\E)(?:\Q$char\E){$len}(?!\Q$char\E)//) {
$cnt++;
}
return $cnt;
}
--------------------
ポイントは、「pに挟まれていないpのX個連続」を探すようにすることです。
    • good
    • 0
この回答へのお礼

御礼が遅くなり申し訳ございません。
有り難うございました。

お礼日時:2005/09/21 12:24

ちょっと解らないのですが、



text1.txtの中身と、実行後のtext1out.txtの中身を教えてください。

text1.txtの中身は、「pphhhppph~」のような行が“複数行”入っている、と考えていいのでしょうか?
「while」ループで“全行”に対してチェックして、条件に合えばカウントアップしますが、条件に合おうが合うまいが毎回(全行分)出力はしてますよね。カウンターのクリアもないようですが。
いまいちコードの意味が解らないのですが…。

単純に「pphhhppph~」のような文字列から「X回連続したpはいくつ含まれるか」を知りたいなら、たとえば以下のロジックでどうでしょうか。

1.
与えられた文字列を、「pではない文字」で区切って配列にする。

2.
配列の各要素の文字数を調べ、文字数をキーとするハッシュをカウントアップする。

4.
知りたい連続数がXなら、ハッシュ{'X'}に、目的の値が入っている。

この回答への補足

早々にお返事どうも有難うございます!
本当に助かります!!!
実は、カウントするスクリプトの書き方も
よくわかっていない状況です。。。。

text1.txtの中身は
pphhhppphが何千何万と続いています。つまり改行はありません。
実行後の
text1out.txt
はどんなかたちでもいいのです。
ただ、pの連続数が10のものが何個あったか
だけでもわかるようになっていれば。。。
ただ、pの連続数は2から20まで、
各連続数ごとに何個あったか重複なしにカウントしたいのです。
ややこしくて本当に申し訳ありません。

補足日時:2005/08/14 15:19
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!