Python100本ノック(10/100)

## はじめに
Pythonを行き当たりばったりで触ってきたので
何処までPythonできているのかを見つめ直すために、[自然言語処理100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100
)していきます。
python2ばっかり使っていましたので、慣れるためにpython3でやっていきます。

[Python100本ノック(5/100)](https://qiita.com/ikura1/items/e98c769b43f56d0f2f85)の続きをやっていきます。

問題文と知らない単語に振り回されてしまっています。
読解力がなさすぎる。

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

```python
def n_gram(obj, n):
    return [obj[i: i + n] for i in range(len(obj))
            if i + n <= len(obj)]
text = 'I am an NLPer'
print(n_gram(text, 2))
print(n_gram(text.split(), 2))
```

    ['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
    [['I', 'am'], ['am', 'an'], ['an', 'NLPer']]


n-gramを調べて、nずつに分割すればいいのかなと思い関数を作りました。
単語bi-gram, 文字bi-gramの表記を無視してしまったためこれではダメですね。

教えていただいたコード
if文で実行回数を絞るより、rangeの数を絞る方が文字数も減っていい感じですね。
```
return [obj[i: i + n] for i in range(len(obj) - n + 1)]
```

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

```python
a = 'paraparaparadise'
b = 'paragraph'
n = 2
x = set(n_gram(a, 2))
y = set(n_gram(b, 2))
print(x | y)  # wa
print(x & y)  # seki
print(x - y)  # sa
print('se' in x)
print('se' in y)
```

    {'gr', 'ad', 'ar', 'ra', 'pa', 'ag', 'ap', 'is', 'di'}
    {'ra', 'pa', 'ap', 'ar'}
    {'di', 'ad', 'is'}
    False
    False

setを使った集合計算をしました。
差集合と含むを調べる周りが気になっています。
他に書き方がありそうな気がしています。
nを定義しているのに、使っていない。

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

```python
def template(**attr):
    return '{x}時の{y}は{z}'.format(**attr)
print(template(x=12, y='気温', z=22.4))
```

    12時の気温は22.4

formatを使ってテンプレートを作成しました。
x, y, zだけでもよかったんですが、可変長引数にしました。

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

```python
def cipher(text):
    return ''.join([chr(219 - ord(w)) if w.islower() is True else w for w in text])

hoge = 'Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.'
print(hoge)
hoge = cipher(hoge)
print(hoge)
print(cipher(hoge))
```

    Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.
    Hr Hv Lrvw Bvxzfhv Blilm Clfow Nlg Ocrwrav Foflirmv. Nvd Nzgrlmh Mrtsg Aohl Srtm Pvzxv Svxfirgb Cozfhv. Aigsfi Krmt Czm.
    Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.

前回の反省点を踏まえて、1行にしてみました。

PEP8でis Trueは悪いとなっていますというご指摘を受けました。
今回の場面では、確実に冗長なコードになっているのですさまじく良くない書き方です。
is Noneと混同していて、今まですごい多様していました。
猛省

```
def cipher(text):
    return ''.join([chr(219 - ord(w)) if w.islower() else w for w in text])
```

### **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 word_shuffle(word):
    return word if len(word) <= 4 else word[0] + ''.join(random.sample(word[1:-1], len(word[1:-1]))) + word[-1]

def text_shuffule(attr):
    return ' '.join([word_shuffle(a.strip('.,')) for a in attr.split()])

text = 'I couldn\'t believe that I could actually understand what I was reading : the phenomenal power of the human mind .'
text_shuffule(text)
```




    "I c'ondlut blvieee that I culod aaltlcuy udnaetnrsd what I was rindeag : the paeemhnonl pewor of the hmuan mind "

はじめは、sortedとrandomを使って順番を変えようとしました。
sortedのkeyに、指定するとrandomに引数はいるのでうまくできませんでした。

random.shuffleの関数を発見し、テストしましたがうまく動作せず原因を調べると元オブジェクトを変更する形でした。そのため内包表記内にうまく落す方法が思いつきませんでした。
なので、random.sampleで順番を変更する形にしました。

---
今回は、内包表記や三項演算子・可変引数などを意識して使うようにしました。
最後に、もっと問題をちゃんと読みます。