自然言語処理100本ノック 第1章 準備運動(後半)


第1章の後半の問題を解いた記録。

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

```python
# -*- coding: utf-8 -*-
__author__ = 'todoroki'

def ngram(data, n):
    res = []
    for i in xrange(len(data) - 1):
        res.append(data[i:i + n])
    return res

string = 'I am an NLPer'
print u'文字リストのbi-gram:'
print ngram(string.split(), 2)
print u'文字列のbi-gram:'
print ngram(string, 2)
#=> 文字リストのbi-gram:
#=> [['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
#=> 文字列のbi-gram:
#=> ['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
```

文字列のbi-gramについては、空白も1文字として扱っている。


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

```python
# -*- coding: utf-8 -*-
__author__ = 'todoroki'

def ngram(data, n):
    res = []
    for i in xrange(len(data) - 1):
        res.append(data[i:i + n])
    return res

string1 = 'paraparaparadise'
string2 = 'paragraph'

X = ngram(string1, 2)
Y = ngram(string2, 2)

print u"和集合:"
print list(set(X).union(set(Y)))
print u"積集合:"
print list(set(X).intersection(set(Y)))
print u"差集合:"
print list(set(X).difference(set(Y)))

print u'\'se\'がXに含まれているか?'
print "se" in X
print u'\'se\'がYに含まれているか?'
print "se" in Y
#=> 和集合:
#=> ['ad', 'ag', 'di', 'is', 'ap', 'pa', 'ra', 'ph', 'ar', 'se', 'gr']
#=> 積集合:
#=> ['ap', 'pa', 'ar', 'ra']
#=> 差集合:
#=> ['is', 'ad', 'se', 'di']
#=> 'se'がXに含まれているか?
#=> True
#=> 'se'がYに含まれているか?
#=> False
```

bi-gramの和集合、積集合、差集合についてはsetのメソッドを利用して求めている。



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

```python
# -*- coding: utf-8 -*-
__author__ = 'todoroki'

def func(x, y, z):
    return u"%s時の%sは%s" % (x, y, z)

x = 12
y = u"気温"
z = 22.4
print func(x, y, z)
#=> 12時の気温は22.4
```

テンプレートにはprint文のフォーマット指定を利用。


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

```python
# -*- coding: utf-8 -*-
__author__ = 'todoroki'

def cipher(data):
    res = ""
    for s in data:
        if s.islower():
            res += chr(219-ord(s))
        else:
            res += s
    return res

string = "re1"
print u'暗号化:'
print cipher(string)
print u'復号化:'
print cipher(cipher(string))
#=> 暗号化:
#=> iv1
#=> 復号化:
#=> re1
```

英小文字かどうかはislowerメソッドにて判定。
暗号化したものをもう一度変換をかけると元に戻るという性質があるので、特別に複合を実装する必要なし。


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

```python
# -*- coding: utf-8 -*-
__author__ = 'todoroki'

import random

def typoglycemia(data):
    res = []
    for d in data.split():
        if len(d) > 4:
            pre = d[0]
            suf = d[-1]
            word = list(d[1:-1])
            random.shuffle(word)
            res.append(pre + "".join(word) + suf)
        else:
            res.append(d)
    return " ".join(res)

sentence = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
print typoglycemia(sentence)
#=> I cuodn'lt beevile that I cuold alluacty usdtanrend what I was reidang : the pmeenhnaol peowr of the huamn mind .
```

randomのshuffleメソッドを利用して文字列の内側をシャッフルしている。
もちろん並び替えはランダムなので、毎回出力が異なる。


<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">