言語処理100本ノック 05-06

05. n-gram

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

n-gramとは

検索対象を単語単位ではなく文字単位で分解し、後続の N-1 文字を含めた状態で出現頻度を求める方法。Nの値が1なら「ユニグラム(uni-gram)」、2なら「バイグラム(bi-gram)」、3なら「トライグラム(tri-gram)」と呼ばれる。
全文検索 - Wikipedia

このあたり全くもって専門外なので意味わからなくて固まったけど,やることはシンプル.

解答

import re
def ngram(n,x):
	xw = re.split("\s",x)
	xc = "".join(xw)
	wordgram = [" ".join(xw[w:w+n]) for w in range(len(xw)-n+1)]
	chargram = [xc[c:c+n] for c in range(len(xc)-n+1)]
	print(wordgram)
	print(chargram)
ngram(2,'I am an NLPer')
['I am', 'am an', 'an NLPer']
['Ia', 'am', 'ma', 'an', 'nN', 'NL', 'LP', 'Pe', 'er']

方法としてはどちらもスライスで.
内包表記も少しずつ悩まずに書けるようになってきた.

06. 集合

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

ParaParaParadise - Wikipedia

解答

x,y = 'paraparaparadise','paragraph'
X = set(x[c:c+2] for c in range(len(x)-1))
Y = set(y[c:c+2] for c in range(len(y)-1))

print('X=',X)
print('Y=',Y)
print('和集合:',X.union(Y))
print('積集合:',X.intersection(Y))
print('差集合X-Y:',X.difference(Y))
print('差集合Y-X:',Y.difference(X))

if 'se' in X:
	print('"se"はXに含まれる')
else:
	print('"se"はXに含まれない')
if 'se' in Y:
	print('"se"はYに含まれる')
else:
	print('"se"はYに含まれない')
X= {'pa', 'ad', 'se', 'ap', 'ra', 'is', 'di', 'ar'}
Y= {'pa', 'ag', 'ap', 'gr', 'ra', 'ph', 'ar'}
和集合: {'pa', 'ad', 'se', 'ag', 'ap', 'ra', 'is', 'di', 'gr', 'ar', 'ph'}
積集合: {'ap', 'pa', 'ar', 'ra'}
差集合X-Y: {'di', 'ad', 'se', 'is'}
差集合Y-X: {'ph', 'ag', 'gr'}
"se"はXに含まれる
"se"はYに含まれない

集合X,Yを求めるところと,'se'が含まれるかどうかの判定はさておき.
集合演算について忘れていたのでまとめておく.

集合まわりの演算はsetが便利

(別記事にします)