〜言語処理100本ノック No.05-09〜

## はじめに

前回まで  
[〜言語処理100本ノック No.01-04〜](https://qiita.com/ITNewcomer/items/a440b7bd01dcce194040)

## 環境

Python 3.7.1

## 05. n-gram

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

### 言葉の定義の確認

[コトバンク](https://kotobank.jp/word/Nグラム-1702302)よりn-gramとbi-gramについて
> 任意の文字列や文書を連続したn個の文字で分割するテキスト分割方法
> 特に，nが1の場合をユニグラム（uni-gram），2の場合をバイグラム（bi-gram），3の場合をトライグラム（tri-gram）と呼ぶ．最初の分割後は1文字ずつ移動して順次分割を行う．

つまりコトバンクを文字単位でuni-gramすると`[コ,ト,バ,ン,ク]`
bi-gramすると`[コト,トバ,バン,ンク,]`になると。
なるほど。
文の場合は単語単位でbi-gramすればいい感じですと。

```python
def n_gram(sentence,n,CorW):
    if CorW == 'W':
        sentence = sentence.split(' ')
    elif CorW == 'C':
        sentence = sentence
    else:
        print('n_gram(sentence,n,CorW)')
        print('CorW:Plsease Write C (Character) or W (Word)')
    x_list = list()
    for i in range(len(sentence)-n+1):
        x_list.append(sentence[i:i+n])
    return(x_list)

a = 'I am an NLPer'

print(n_gram(a,2,'C'))
#['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
print(n_gram(a,2,'W'))
#[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
```

## 06. 集合

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

```python
def n_gram(sentence,n,CorW):
    if CorW == 'W':
        sentence = sentence.split(' ')
    elif CorW == 'C':
        sentence = sentence
    else:
        print('n_gram(sentence,n,CorW)')
        print('CorW:Plsease Write C (Character) or W (Word)')
    x_list = list()
    for i in range(len(sentence)-n+1):
        x_list.append(sentence[i:i+n])
    return(x_list)

a = 'paraparaparadise'
b = 'paragraph'

#リストからsetオブジェクトにして集合関数を使う
X = set(n_gram(a,2,'C'))
Y = set(n_gram(b,2,'C'))

print('和集合')
print(X | Y)
# {'pa', 'ag', 'ar', 'di', 'se', 'ad', 'ph', 'ra', 'ap', 'gr', 'is'}
print('積集合')
print(X & Y)
# {'pa', 'ar', 'ap', 'ra'}
print('差集合')
print(X - Y)
# {'is', 'ad', 'se', 'di'}
se = {'se'}
print(se <= X)
print(se <= Y)
```

## 07. テンプレートによる文生成

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

```python
x = 2
y = '気温'
z = 22.4

def template(x,y,z):
    print(str(x) + '時の' + str(y) + 'は' + str(z))

template(x,y,z)
```

## 08. 暗号文

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

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

print(cipher('Test aNd test'))
```

## 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(sentence):
    mylist = sentence.split(' ')
    new_list = list()
    for i in mylist:
        if len(i) <= 4:
            new_list.append(i)
        else:
            temp = i[1:len(x)-1]
            temp = ''.join(random.sample(temp, len(temp)))
            new_list.append(i[0] + temp + i[len(i)-1])
    return ' '.join(map(str, new_list))

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

## 最後に

なんかコードが冗長な気がしますね。
ある程度進んだら見返してみて、もっと簡潔になるか確認してみます。
なにかお気づきの点あればコメントいただけると幸いです。