微忘録

好奇心に記憶力がついていかない人のブログ

2015年度版NLP100本ノック第1章をPython3で解く

Djangoアプリへの導入などを考えて、Pythonでやり直したいと思い挑戦したので備忘録。
各コードの実行結果はこちらのリポジトリにて公開しています。

第1章: 準備運動

00. 文字列の逆順

文字列"stressed"の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ

word = "stressed"
print(word[::-1])

01. 「パタトクカシーー」

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

#単純に2飛ばしで
word = "パタトクカシーー"
print(word[::2])

02. 「パトカー」+「タクシー」=「パタトクカシーー」

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

#分割する文字列と、格納するリストを作成
word = "パタトクカシーー"
word_li =[]

#特定の順番の文字を分割し、リストに要素として格納する
for i in range(1,len(word),2) :
    word_li.append(word[i])

#リスト内文字をスペース無しで連結する
word_li = "".join(word_li)    
print(word_li)

03. 円周率

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

#すでに分かち書きされているので、半角スペースごとに分解してリストに格納。
sentence = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
sentence_li =[]
sentence_li = sentence.split(" ")
#リストを各単語の(アルファベットの)文字数を先頭から出現順に並べる
sorted(sentence_li,key=len)

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文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.

#単語に分解
sentence = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
sentence_li = sentence.split(" ")

sentence_dict = {}
topword = [1, 5, 6, 7, 8, 9, 15, 16, 19]

for i in sentence_li:
    if sentence_li.index(i) + 1 in topword:
        sentence_dict[i[:1]] = sentence_li.index(i) + 1
    else:
        sentence_dict[i[:2]] = sentence_li.index(i) + 1
        
print(sentence_dict)

05. n-gram

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

#n-gram関数作り
def ngram(input, n):
    result = []
    for i in range(0, len(input) - n + 1):
        result.append(input[i:i + n])

    return result

#文章用意
sentence = "I am an NLPer"

#単語n-gram(分かち書き)
sentence_li = sentence.split(" ")
ngram(sentence_li, 2)

#文字n-gram(文字区切り)
ngram(sentence, 2)

06. 集合

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

sentence1 = "paraparaparadise"
sentence2 = "paragraph"

#bi-gram結果をset型で重複無し
X = set(ngram(sentence1,2))
Y = set(ngram(sentence2,2))

#和集合
X | Y

#積集合
X & Y

#差集合
X - Y

#seを含むか確認
'se' in X
'se' in Y

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

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

def xyz_def(x,y,z) :
    print(str(x) + "時の" + str(y) + "は" + str(z))
    
xyz_def(x=12, y="気温", z=22.4)
def xyz_def(x, y, z):
    print( '{hour}時の{subject}は{value}'.format(hour=x, subject=y, value=z))

xyz_def(x=12, y="気温", z=22.4)

08. 暗号文

与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.

英小文字ならば(219 - 文字コード)の文字に置換 その他の文字はそのまま出力 この関数を用い,英語のメッセージを暗号化・復号化せよ.

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

cipher("oh,myパスタ")

09. Typoglycemia

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

import random

def sliceRandom(input) :
    text = input.split(" ")
    result = []
    for i in text:
        if len(i) <= 4:
            result.append(i)
        else:
            ramdomed = list(i[1:-1])
            random.shuffle(ramdomed)
            result.append(i[0] + "".join(ramdomed) + i[-1])
    return "".join(result)

sliceRandom("I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind .")