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

こんにちは、Perl 6アドベントカレンダーの二日目の投稿になります。

NLP 5本ノックということで、東北大学の言語処理100本ノックの『第1章: 準備運動』の 00~04までの5本をPerl 6で解きつつ解説をしていきたいと思います。

問題文は掲載しませんので、ブラウザの別窓で下記ページを参照しながらお楽しみください：
http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch1

# 読み進める前に

## 注意!
+ 読者レベルとしては、[Perl 6アドベントカレンダー1日目](http://qiita.com/titsuki/items/549ac95b8c37feb1dee1)で紹介した[Perl 6 introduction](https://github.com/hankache/perl6intro)などのチュートリアルを一通り終えたレベルを想定しています。
+ わかりやすく紹介するために、正確ではない表現がところどころ出てくるかもしれません。
 + より正確な情報を知りたい場合は、[Perl 6アドベントカレンダー1日目](http://qiita.com/titsuki/items/549ac95b8c37feb1dee1)で紹介した[公式ドキュメント](http://qiita.com/titsuki/items/549ac95b8c37feb1dee1#%E5%85%AC%E5%BC%8F%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88) や公式テストケースの[roast](http://qiita.com/titsuki/items/549ac95b8c37feb1dee1#roast)などを参照ください。
+ 日本語訳が定着していないようなPerl 6独特の英単語を目にするかもしれません。基本的に解説中ではそのまま英単語で書き、その後補足しますのでご容赦ください。
+ Perl 6のモットーはTMTOWTDI (やり方は一つじゃない) です。特に正解はありません。でも、「これのほうがもっとかっこよく簡潔に書けるよ！」といった指摘は大歓迎です！

# 00. 文字列の逆順

## コード

```pl:00.p6
"stressed".flip.say;
```

## 解説

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

## 補足

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

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

## コード

```pl: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. 「パトカー」＋「タクシー」＝「パタトクカシーー」

## コード

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

## 解説

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

# 03. 円周率

## コード

```pl: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. 元素記号

## コード

```pl: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　でした。