LoginSignup
0
2

More than 5 years have passed since last update.

Perl 6でNLP 5本ノック 『第1章: 準備運動』 00 ~ 04

Last updated at Posted at 2016-12-01

こんにちは、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独特の英単語を目にするかもしれません。基本的に解説中ではそのまま英単語で書き、その後補足しますのでご容赦ください。
  • Perl 6のモットーはTMTOWTDI (やり方は一つじゃない) です。特に正解はありません。でも、「これのほうがもっとかっこよく簡潔に書けるよ!」といった指摘は大歓迎です!

00. 文字列の逆順

コード

00.p6
"stressed".flip.say;

解説

  1. .flipを使いinvocant (i.e. "stressed")の文字列を逆順にします
  2. .sayで文字列を出力します

補足

  • invocant
    • インボカント と読みます
    • メソッドの呼び出し元のインスタンスのことです

01. 「パタトクカシーー」

コード

01.p6
"パタトクカシーー".comb[1,3,5,7].trans(" " => "").say;

解説

  1. .combで文字列を文字単位に区切り、リストにします
  2. [1,3,5,7]でリスト中の1,3,5,7番目の要素だけを選択します
  3. .transで空白文字を詰めます(.transはinvocant (i.e. 2.の出力)をStr型とみなしています)
  4. .sayで文字列を出力します

02. 「パトカー」+「タクシー」=「パタトクカシーー」

コード

02.p6
("パトカー".comb >>~<< "タクシー".comb).trans(" " => "").say;

解説

  1. "パトカー".combでリスト("パ","ト","カ",”ー")を作ります
  2. "タクシー".combでリスト("タ","ク","シ","ー")を作ります
  3. >>~<<でリスト内の文字同士を結合します。具体的には、 "パ" と "タ"、"ト" と "ク"、"カ" と "シ"、”ー" と "ー"をこの順番で結合し、新たなリストを生成します
  4. .transで空白文字を詰めます(.transはinvocant (i.e. 3.の出力)をStr型とみなしています)
  5. .sayで文字列を出力します

03. 円周率

コード

03.p6
"Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."\
.trans(("," => ""),("." => ""))\
.words\
.map({ ($_, .chars) })\
.say;

解説

  1. .transでinvocantの文字列中の","と"."を詰めます
  2. .wordsで空白単位で文字列を分割し、リストを生成します
  3. .mapでそれぞれの単語を(《単語》, 《その単語の文字数》)のリストに変換します
  4. .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;

解説

  1. .transでinvocantの文字列中の","と"."を詰めます
  2. .wordsで空白単位で文字列を分割してリストを生成し、@wordsに代入します
  3. gather for takeイディオムを用いて@wordsの添え字ひとつひとつを見ていき、それを利用して遅延リストを生成します
    1. if $_ == any [1, 5, 6, 7, 8, 9, 15, 16, 19]で添え字が1, 5, 6, 7, 8, 9, 15, 16, 19のいずれかに一致するのかどうかを調べます
    2. もし一致した場合は: (《その添え字の位置の単語の先頭文字》,《添え字》)のリストを取得します
    3. 一致しなかった場合は: (《その添え字の位置の単語の先頭二文字》,《添え字》)のリストを取得します
  4. .flatでリストを平たん化します
  5. .hashでリストをハッシュにします
  6. .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 でした。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2