こんにちは、Perl 6アドベントカレンダーの二日目の投稿になります。
NLP 5本ノックということで、東北大学の言語処理100本ノックの『第1章: 準備運動』の 00~04までの5本をPerl 6で解きつつ解説をしていきたいと思います。
問題文は掲載しませんので、ブラウザの別窓で下記ページを参照しながらお楽しみください:
http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch1
読み進める前に
注意!
- 読者レベルとしては、Perl 6アドベントカレンダー1日目で紹介したPerl 6 introductionなどのチュートリアルを一通り終えたレベルを想定しています。
- わかりやすく紹介するために、正確ではない表現がところどころ出てくるかもしれません。
- より正確な情報を知りたい場合は、Perl 6アドベントカレンダー1日目で紹介した公式ドキュメント や公式テストケースのroastなどを参照ください。
- 日本語訳が定着していないようなPerl 6独特の英単語を目にするかもしれません。基本的に解説中ではそのまま英単語で書き、その後補足しますのでご容赦ください。
- Perl 6のモットーはTMTOWTDI (やり方は一つじゃない) です。特に正解はありません。でも、「これのほうがもっとかっこよく簡潔に書けるよ!」といった指摘は大歓迎です!
00. 文字列の逆順
コード
00.p6
"stressed".flip.say;
解説
-
.flip
を使いinvocant (i.e. "stressed")の文字列を逆順にします -
.say
で文字列を出力します
補足
- invocant
- インボカント と読みます
- メソッドの呼び出し元のインスタンスのことです
01. 「パタトクカシーー」
コード
01.p6
"パタトクカシーー".comb[1,3,5,7].trans(" " => "").say;
解説
-
.comb
で文字列を文字単位に区切り、リストにします -
[1,3,5,7]
でリスト中の1,3,5,7番目の要素だけを選択します -
.trans
で空白文字を詰めます(.trans
はinvocant (i.e. 2.の出力)をStr型とみなしています) -
.say
で文字列を出力します
02. 「パトカー」+「タクシー」=「パタトクカシーー」
コード
02.p6
("パトカー".comb >>~<< "タクシー".comb).trans(" " => "").say;
解説
-
"パトカー".comb
でリスト("パ","ト","カ",”ー")
を作ります -
"タクシー".comb
でリスト("タ","ク","シ","ー")
を作ります -
>>~<<
でリスト内の文字同士を結合します。具体的には、 "パ" と "タ"、"ト" と "ク"、"カ" と "シ"、”ー" と "ー"をこの順番で結合し、新たなリストを生成します -
.trans
で空白文字を詰めます(.trans
はinvocant (i.e. 3.の出力)をStr型とみなしています) -
.say
で文字列を出力します
03. 円周率
コード
03.p6
"Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."\
.trans(("," => ""),("." => ""))\
.words\
.map({ ($_, .chars) })\
.say;
解説
-
.trans
でinvocantの文字列中の","と"."を詰めます -
.words
で空白単位で文字列を分割し、リストを生成します -
.map
でそれぞれの単語を(《単語》, 《その単語の文字数》)
のリストに変換します -
.say
でリストを出力します
04. 元素記号
コード
04.p6
my @words = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."\
.trans(("," => ""),("." => ""))\
.words;
gather for ^@words {
if $_ == any [1, 5, 6, 7, 8, 9, 15, 16, 19] {
take (@words[$_].comb.head, $_)
} else {
take (@words[$_].comb.[^2].join, $_)
}
}.flat.hash.say;
解説
-
.trans
でinvocantの文字列中の","と"."を詰めます -
.words
で空白単位で文字列を分割してリストを生成し、@words
に代入します -
gather for take
イディオムを用いて@words
の添え字ひとつひとつを見ていき、それを利用して遅延リストを生成します -
if $_ == any [1, 5, 6, 7, 8, 9, 15, 16, 19]
で添え字が1, 5, 6, 7, 8, 9, 15, 16, 19のいずれかに一致するのかどうかを調べます - もし一致した場合は:
(《その添え字の位置の単語の先頭文字》,《添え字》)
のリストを取得します - 一致しなかった場合は:
(《その添え字の位置の単語の先頭二文字》,《添え字》)
のリストを取得します -
.flat
でリストを平たん化します -
.hash
でリストをハッシュにします -
.say
でハッシュを出力します
補足
any [1, 5, 6, 7, 8, 9, 15, 16, 19]
- これはJunction型のインスタンスを生成します
- より詳しく知りたい方は公式ドキュメントをご覧になってください: https://docs.perl6.org/type/Junction
以上、Perl 6でNLP 5本ノック 『第1章: 準備運動』 00 ~ 04 でした。