いくつか登録しているメールマガジンの中で、毎号来る度にわくわくするのが結城浩さん主催のPerlクイズです。
パズルの回はたま~に読んでてPerlDrunkerになりそうな解答が来たりするのも楽しみのひとつかな(笑)
最新号の問題は自力で解けるかどうかで、より難しいプログラムと向き合えるかが判断できそうな良質な問題だと思います。
Perlの勉強をしてる人、今回の問題に取り組んでみることを強く推奨します、はい。
問題については、バックナンバーで最新号も読めるのでこちらを参照しましょう。
問題の骨子は「関数is_balancedの内容を記述すべし」です。
もっとも、問題で考えるべきところは括弧の対応の判別をどういった手段で行うかという部分なのですね。
解法として簡単に思いつく手段は、「正規表現を使う」と「文字列分解して力技でゴリゴリ」といったところが有力。
後者の手段は個人的に美しくなくてイヤ。とか言ってるとtrickyでcoolな解答が解答編のメールで来そうな気がします(笑)。
そんなわけで、前者の正規表現を利用した方法で解きたいと思います。
で、私が考えた安直な解答はこんな感じ。
[code]
sub is_balanced {
my $string = shift;
my $ret;
while( $string =~ /\([^()]*\)/ ){
$string =~ s/\([^()]*\)//;
}
if( $string eq ” ){
$ret = 1;
}
return $ret;
}
[/code]
今回私が利用した正規表現は「 \([^()]*\)」です。
この意味は「(]から始まり、「(」と「)」を除外した文字要素の0回以上の繰り返し、「)」で終わるです。
プログラム中$stringが与えられた文字列、$retが戻り値用の変数となっています。
処理内容としては
$string中に上記の正規表現が見つかったらマッチ部分を除去。
正規表現がマッチしなくなるまで置換処理のループを回る。
です。
そして、ループを抜けたところで$stringの内容を確認して$retへ戻り値を与えてます。
最終的に$stringが空文字列となっていたらカッコの対応が取れているということになりますので$retに1を与えています。
空文字列にならなかった場合は$retの初期値0が戻り値になり0が返されます。
これで題意を満たす関数となりました。実行結果もばっちりだったのでOK、と。
Perl界隈(どこだそれ)で著名な方たちの顎が外れそうな解答を期待して解答編を気長に待とうと思います。