せっかくだし自然言語処理100本ノック1章(準備運動)

# はじめに

東北大学の[乾・岡崎研究室](http://www.cl.ecei.tohoku.ac.jp)で公開されている「[言語処理100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100/)」は言語処理を学ぶ学生や社会人を対象とした問題集として有名です。

ということで僕も東北大生なので、専攻違うけど[言語処理100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100/)やってみました。

# 第1章: 準備運動

## 00. 文字列の逆順
> 文字列"stressed"の文字を逆に（末尾から先頭に向かって）並べた文字列を得よ．


```python
words = "stressed"
print(words[::-1])
```

[結果]
    desserts
    

## 01. 「パタトクカシーー」
> 「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ．


```python
words = "パタトクカシーー"
print(words[::2])
```

[結果]
    パトカー
    

## 02. 「パトカー」＋「タクシー」＝「パタトクカシーー」
> 「パトカー」＋「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ．


```python
word1 = "パトカー"
word2 = "タクシー"
for i in range(4):
    print(word1[i]+word2[i],end="")
```

[結果]
    パタトクカシーー

※pythonのprintで改行したくないときは引数end=''でおk。(デフォルトはend='\n')

## 03. 円周率
> "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."という文を単語に分解し，各単語の（アルファベットの）文字数を先頭から出現順に並べたリストを作成せよ．


```python
PI = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
PI = PI.replace('.','')
PI = PI.replace(',','')
PI = PI.split()
ans = [len(num) for num in PI]
ans
```

[結果]
    [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

※積極的に内包表記を使っていくスタイル

## 04. 元素記号
> "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."という文を単語に分解し，1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字，それ以外の単語は先頭に2文字を取り出し，取り出した文字列から単語の位置（先頭から何番目の単語か）への連想配列（辞書型もしくはマップ型）を作成せよ．


```python
element = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
dict = {}
list = [1,5,6,7,8,9,15,16,19]
for i,j in enumerate(element.split()):
    if i+1 in list:
        dict[i+1] = j[0]
    else:
        dict[i+1] = j[0:2]
print(dict)
```

[結果]
    {1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O', 9: 'F', 10: 'Ne', 11: 'Na', 12: 'Mi', 13: 'Al', 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 18: 'Ar', 19: 'K', 20: 'Ca'}
    

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


```python
def n_gram(target, n):
    result = []
    for i in range(len(target) - n + 1):
        result.append(target[i:i + n])
    return result

target = "I am an NLPer"
words_target = target.split()

print("[単語bi-gram]")
print(n_gram(words_target, 2))
print("[文字bi-gram]") 
print(n_gram(target, 2))
```

[結果]
    [単語bi-gram]
    [['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
    [文字bi-gram]
    ['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
    

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


```python
def n_gram(target, n):
    result = []
    for i in range(0,len(target) - n + 1):
        result.append(target[i:i + n])
    return result

text_x = "paraparaparadise"
text_y = "paragraph"

set_x = set(n_gram(text_x, 2))
set_y = set(n_gram(text_y, 2))

print("X:",end="")
print(set_x)
print("Y:",end="")
print(set_y)

print("----")

print("[和集合]")
# print(set_x | set_y)でもOK
print(set_x.union(set_y))

print("[積集合]")
# print(set_x & set_y)でもOK
print(set_x.intersection(set_y))

print("[差集合]")
# print(set_x - set_y)でもOK
print(set_x.difference(set_y))

print("----")

print("se in X: ",end="")
print('se' in set_x)
print("se in Y: ",end="")
print('se' in set_y)
```

[結果]
    X:{'ar', 'ap', 'ad', 'di', 'ra', 'pa', 'se', 'is'}
    Y:{'ar', 'ap', 'ag', 'gr', 'ph', 'ra', 'pa'}
    ----
    [和集合]
    {'ar', 'ap', 'ag', 'ad', 'gr', 'ph', 'di', 'ra', 'pa', 'se', 'is'}
    [積集合]
    {'pa', 'ar', 'ap', 'ra'}
    [差集合]
    {'is', 'ad', 'di', 'se'}
    ----
    se in X: True
    se in Y: False
    

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


```python
def createSentence(x,y,z):
    print("{}時の".format(x) + y + "は{}".format(z))

createSentence(12,"気温",22.4)
```

[結果]
    12時の気温は22.4
    

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


```python
def cipher(s):
    result =''
    for i in s:
        if i.islower():
            result += chr(219-ord(i))
        else:
            result += i
    return result

text = "Man is but a reed, the most feeble thing in the nature, but he is a thinking reed. "
cipher(text)
```

[結果]
    'Mzm rh yfg z ivvw, gsv nlhg uvvyov gsrmt rm gsv mzgfiv, yfg sv rh z gsrmprmt ivvw. '


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


```python
import random

def typoglycemia(target):
    res = []
    for s in target.split():
        if len(s) < 5:
            res.append(s)
        else:
            head = s[0]
            tail = s[-1]
            inner = list(s[1:-1])
            random.shuffle(inner)
            res.append(head+"".join(inner)+tail)
    return " ".join(res)

target = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
print(typoglycemia(target))
```

[結果]
     I cud'lont bivleee that I colud aaclutly unnsetadrd what I was rindaeg : the phnomeneal pwoer of the human mind .
    

# さいごに
間違い等ありましたらご指摘ください。修正いたします。