言語処理100本ノックに挑戦 第1章

# 機械学習とか以前の問題
前職でデータ分析に携わってから統計解析に興味を持ち、機械学習に興味を持った。

機械学習ではpythonというプログラミング言語がよく使われているらしい。
VBAとかでプログラミング自体の楽しさは実体験としてあるし、やってみたい。やってみよう。

とりあえず、入門書は一周した。
軽いスクレイピングツールも作れるようになった。
そろそろ機械学習を実装してみよう。

というところで挫折。
業務で使わないということもあり、pythonでコードを書く、という経験が足りなさすぎる。
書く練習として良い題材はないか、と探していたところ、これに漂着。
最後の方には機械学習の周辺分野にも触れるらしいし、当分はこれと並行して数学をやれば良いのかな、
という結論に達した。

ということで、１日に何問かのペースで解いていこうと思う。
１問目から解いてはいるが、結果を残そうと思い立ったのがそこそこ解いてからだったので、５問目から。

#第１章

##05. n-gram
与えられたシーケンス（文字列やリストなど）からn-gramを作る関数を作成せよ．
この関数を用い，"I am an NLPer"という文から単語bi-gram，文字bi-gramを得よ．

```py3:ngram.py
# -*- coding: utf-8 -*-

def get_ngram(str_pattern, N=2):
    return [str_pattern[i:i + N] for i, x in enumerate(str_pattern) if len(str_pattern[i:i + N]) == N]
```

```py3
import ngram
string = "I am an NLPer"

# 単語bi-gram
ngram.get_ngram(string.split())

Out[5]: 
[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]

# 文字bi-gram
ngram.get_ngram(string.replace(' ', ''))

Out[7]: 
['Ia', 'am', 'ma', 'an', 'nN', 'NL', 'LP', 'Pe', 'er']
```

## 06. 集合
"paraparaparadise"と"paragraph"に含まれる文字bi-gramの集合を，それぞれ, XとYとして求め，XとYの和集合，積集合，差集合を求めよ．
さらに，'se'というbi-gramがXおよびYに含まれるかどうかを調べよ．

```py3:
import ngram
X = set(ngram.get_ngram("paraparaparadise"))
Y = set(ngram.get_ngram("paragraph"))

# 和集合
'X | Y : {0}'.format(X | Y)
Out[41]: 
"X | Y : {'ag', 'ph', 'di', 'gr', 'ap', 'ar', 'ra', 'is', 'se', 'pa', 'ad'}"

# 差集合
'X - Y : {0}'.format(X - Y)
Out[43]: 
"X - Y : {'di', 'is', 'se', 'ad'}"

'Y - X : {0}'.format(Y - X)
Out[44]: 
"Y - X : {'ag', 'ph', 'gr'}"

# 積集合
'X & Y : {0}'.format(X & Y)
Out[46]: 
"X & Y : {'ra', 'ap', 'ar', 'pa'}"

'se' in str(X)
Out[47]: 
True

'se' in str(Y)
Out[48]: 
False
```

## 07. テンプレートによる文生成
引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ．さらに，x=12, y="気温", z=22.4として，実行結果を確認せよ．

```py3:sentense.py
# -*- coding: utf-8 -*-

def make_sentense(x, y, z):
    return '{0}時の{1}は{2}'.format(x, y, z)
```

```py3
import sentence

sentence.make_sentense(12, '気温', 22.4)
Out[50]: 
'12時の気温は22.4'
```

## 08. 暗号文
与えられた文字列の各文字を，以下の仕様で変換する関数cipherを実装せよ．
 ・英小文字ならば(219 - 文字コード)の文字に置換
 ・その他の文字はそのまま出力
この関数を用い，英語のメッセージを暗号化・復号化せよ．

```py3:encrypter.py
# -*- coding: utf-8 -*-

def cipher(string):
    return ''.join(chr(219 - ord(char)) if 'a' <= char <= 'z' else char for char in string)
```

```py3
import encrypter
string = "Hello, world!"

encrypter.cipher(string)
Out[53]: 
'Hvool, dliow!'
```


## 09. Typoglycemia
スペースで区切られた単語列に対して，各単語の先頭と末尾の文字は残し，それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ．ただし，長さが４以下の単語は並び替えないこととする．適当な英語の文（例えば"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."）を与え，その実行結果を確認せよ．

```py3:Typoglycemia.py
# -*- coding: utf-8 -*-

import random

def typoglycemia(string):
    return ' '.join(word[0] + ''.join(random.sample(word[1:-1], len(word[1:-1]))) + word[-1]
                    if len(word) >= 4 else word for word in string.split())
```

```py3
import Typoglycemia
string = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."

Typoglycemia.typoglycemia(string)
Out[56]: 
"I cloun'dt bievele that I cloud aluclaty uarstnnedd what I was renaidg : the pamnheonel pewor of the hamun mnid ."
```

## 反省
ワンライナーにこだわりすぎて、読みづらい＆時間がかかりすぎている気がする。。。