言語処理100本ノック第1章: 準備運動の俺の解答。その他の章はこちら。
00~04
略
05. n-gram
def ngram(n, s):
l = []
for i in range(0, len(s) - (n - 1)):
l.append(tuple(s[i:i+n]))
return l
s = "I am an NLPer"
# 単語bigram
print(ngram(2, s.split(" ")))
# 文字bigram
print(ngram(2, list(s)))
この解答では扱わなかったけど、n-gramにおいて、BOSやEOSを扱ったほうが実用上はいい場合も多いだろうな、とは、ちょっと思った。例えばbigramでBOSと最初の単語のペアを1要素とする、とか。1トークンしかない文もあるしね。
06. 集合
さっきの問題で定義した関数ngram()を使っています。
差集合というのは、X-YとY-Xの両方ありますね。
s_x = "paraparaparadise"
s_y = "paragraph"
bi_x = set(ngram(2, list(s_x)))
bi_y = set(ngram(2, list(s_y)))
# 和
print(bi_x | bi_y)
# 積
print(bi_x & bi_y)
# 差
print(bi_x - bi_y)
print(bi_y - bi_x)
# seが含まれるかどうか
print(('s', 'e') in bi_x)
print(('s', 'e') in bi_y)
07. テンプレートによる文生成
x=12, y=”気温”, z=22.4というふうに整数、文字列、浮動小数点数を織り交ぜているのは、変数にどんな型が来てもいいようにしておけよ、という出題者の意図を感じました。
def nlp100_07(x, y, z):
return str(x) + "時の" + str(y) + "は" + str(z)
08. 暗号文
def cipher(s: str):
r = []
for c in list(s):
if c.islower():
r.append(chr(219 - ord(c)))
else:
r.append(c)
return ''.join(r)
ciphered = cipher("My name is Sen Yoshida.")
print(ciphered)
print(cipher(ciphered))
2回適用すると元に戻るんですね。Y=219-XだからX=219-Y。方程式の変形なんて久しぶりにやって、ちょっと嬉しい。
09. Typoglycemia
ここまでの問題は関数を作ればよかったけど、ここで初めてコマンドを作れという問題になっている。Windowsで作業しているのでUNIXシェルどうしようかと色々試し、Cygwinにした。なお開発環境はAnacondaのSpyder。pythonはAnacondaのものを使う。そのためCygwin側の.bash_profileに下記を書いている:
export PATH=$PATH:/cygdrive/c/Users/俺/anaconda3:/cygdrive/c/Users/俺/anaconda3/Library/bin'
で、解答:
import sys
import random
def typoglycemia(s: str):
words = s.split(" ")
l = []
for w in words:
if len(w) > 4:
t = [w[0]]
mid = list(w[1:len(w) - 1])
random.shuffle(mid)
t += mid
t.append(w[len(w) - 1])
l.append(''.join(t))
else:
l.append(w)
return ' '.join(l)
for s in sys.stdin:
print(typoglycemia(s))
この現象を題材にされたのは、いいですね。楽しみながら学ぶことができる。そして私は知らなかったんですけど、この例文ってデマっぽい感じなんですね…