はじめに
言語処理の問題集として有名な、言語処理100本ノックを解いた回答をまとめてます。
今回は前回の続きになります。
第1章:準備運動
05. n-gram
与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.
phrase2 = "I am an NLPer"
def n_gram(phrase, n, word=True):
outcome_list = []
if word == True:
phrase_list = phrase.split()
for i in range(len(phrase_list) - n + 1):
outcome_list.append(phrase_list[i:i+n])
return outcome_list
else: #incluede or exclude space?
phrase = phrase.replace(" ", "")
for i in range(len(phrase) - n + 1):
outcome_list.append(phrase[i:i+n])
return outcome_list
print(n_gram(phrase2, 2, word=True))
print(n_gram(phrase2, 2, word=False))
>[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
>['Ia', 'am', 'ma', 'an', 'nN', 'NL', 'LP', 'Pe', 'er']
N-gramに関する問題です。
N-gramについては以下の記事を参照してください。
このN-gramは英語を想定して作成しています。文字単位か単語単位かを指定して、それぞれについて、空のリストに分割された文字列を追加しています。
06. 集合
“paraparaparadise”と”paragraph”に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,’se’というbi-gramがXおよびYに含まれるかどうかを調べよ.
x = "paraparaparadise"
y = "paragraph"
X = n_gram(x, 2, word=False)
Y = n_gram(y, 2, word=False)
def set_func(z):
lst = set()
for i in range(len(z)):
lst.add(z[i])
return lst
X = set_func(X)
Y = set_func(Y)
X_or_Y = X | Y
X_and_Y = X & Y
X_but_Y = X - Y
print (X_or_Y, X_and_Y, X_but_Y)
print("se is in X? :", "se" in X)
print("se is in Y? :", "se" in Y)
>{'pa', 'di', 'se', 'ap', 'ad', 'ar', 'is', 'ag', 'ph', 'ra', 'gr'} {'ar', 'pa', 'ap', 'ra'} {'ad', 'is', 'di', 'se'}
>se is in X? : True
>se is in Y? : False
ポイント
set( ), { }
setオブジェクト ・集合を表現するオブジェクト ・集合の演算に用いることができる setオブジェクトの用例 add( ):オブジェクトに要素を追加 |, union( ):和集合、A∪B &, intersection( ):積集合、A∩B -, difference( ):差集合、A∩‾B(Bの上に棒線)
前の問題で作成したN-gramを利用しています。
あとは、それぞれの単語のbigramをsetオブジェクトにして、和集合・積集合・差集合をとっています。
07. テンプレートによる文生成
引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ.
x1 = 12
y1 = "気温"
z1 = 22.4
def template(x, y, z):
return "{}時の{}は{}".format(x, y, z)
print(template(x1, y1, z1))
>12時の気温は22.4
ポイント
"{ }".format( )
format( )関数 ・文字列に変数を埋め込める関数
これは実にシンプルです。format( )関数を用いてます。
08. 暗号文
与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
・英小文字ならば(219 – 文字コード)の文字に置換
・その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.
def cipher(word, encryption=True):
coded = ""
decoded = ""
alpha = "abcdefghijklmnopqrstuvwxyz"
if encryption == True:
for x in word:
if x in alpha:
coded += (chr(219 - ord(x)))
else:
coded += x
return coded
else:
for x in word:
if x in alpha:
decoded += chr(219 - ord(x))
else:
decoded += x
return decoded
print(cipher("abdあ"))
print(cipher("zywあ", encryption=False))
>zywあ
>abdあ
ポイント
ord( )
chr( )
ord( )関数 ・入力された文字のアスキーコードをreturnする関数 chr( )関数 ・入力されたアスキーコードに対応する文字をreturnする関数
暗号化する場合は、encryption=True、複合化する場合は、encryption=Falseに設定するようにしています。
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
phrase2 = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
def shuffle_func(phrase):
lst = phrase.split()
shffl_lst = []
for word in lst:
if len(word) <=4:
shffl_lst.append(word)
else:
cap_lst = []
for i in range(1, len(word) - 1):
cap_lst.append(word[i])
random.shuffle(cap_lst)
cap_shuffled = ""
for x in cap_lst:
cap_shuffled += x
word2 = word[0] + cap_shuffled + word[len(word) - 1]
shffl_lst.append(word2)
shuffled = shffl_lst[1]
for i in range(1, len(shffl_lst)):
shuffled = shuffled + " " + shffl_lst[i]
return shuffled
print(shuffle_func(phrase2))
>c'duolnt c'duolnt beleive that I colud atullcay udrnatsned what I was rdeniag : the pahnenoeml pweor of the hmaun mind .
ポイント
random
randomモジュール ・標準ライブラリに備えられているモジュール ・ランダムな数値の生成に使用する random.shuffle( ):入力されたリストの中身の順番をランダムに入れ替えてreturnする関数 random.random( ):0以上1未満の浮動小数点数をreturnする関数
まず、与えられた単語列を単語で分割してリストに入れます。
その後、単語の長さが5以上の場合は上記のrandom.shuffle( )関数を用いて文字列を並び替えています。
以上、第1章の問題の回答でした。次回の投稿では第2章について扱おうかと思います。