言語処理100本ノック2020 第1章 準備運動

はじめに

言語処理100本ノック2020

言語処理100本ノックは東北大学が公開している自然言語処理の問題集です。

とても良質なコンテンツで企業の研修や勉強会で使われています。

そんな言語処理100本ノックが2020年に改定されてました。昨今の状況を鑑みて、深層ニューラルネットワークに関する問題が追加されました。(その他にも細かい変更があります)

この記事では、言語処理100本ノック2020にPythonで取り組んでいきます。

他にも色々な解法があると思うので、一つの解答例としてご活用ください!

全100問の解説に戻る

00. 文字列の逆順

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

1
2
s = 'stressed'
print (s[::-1])

pythonの文字列はスライスを利用することで逆順に取得することができます。

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

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

1
2
s = 'パタトクカシーー'
print (s[::2])

ストライド(ステップ)を利用するのが良いでしょう。

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

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

1
2
3
s1 = 'パトカー'
s2 = 'タクシー'
print (''.join([a+b for a,b in zip(s1,s2)]))

zipを使って二つの文字列に対してループを回すのが良いでしょう。
最後の''.join()文字列のリストを結合し文字列に変換する処理です。

03. 円周率

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

1
2
3
s = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
s = s.replace(',','').replace('.','')
[len(w) for w in s.split()]

まず、単語の文字数を数えるのに邪魔なので、,.を削除します。その後split()を利用して文章を半角スペースを区切り文字として分割します。

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

1
2
3
4
5
6
7
8
9
10
11
s = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
s = s.replace('.','')
idx = [1, 5, 6, 7, 8, 9, 15, 16, 19]
mp = {}
for i,w in enumerate(s.split()):
if (i+1) in idx:
v = w[:1]
else:
v = w[:2]
mp[v] = i+1
print (mp)

前回の問題の知識に加えて、辞書の扱いが求められます。
pythonでは辞書は{}のようにして作成します。

05. n-gram

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

1
2
3
4
5
6
7
8
def ngram(S, n):
r = []
for i in range(len(S) - n + 1):
r.append(S[i:i+n])
return r
s = 'I am an NLPer'
print (ngram(s.split(),2))
print (ngram(s,2))

スライスを利用することで、n-gramを表現できます。スライスは文字列にもリストにも利用できるため、単語bi-gramにも文字bi-gramにも使えます。

06. 集合

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def ngram(S, n):
r = []
for i in range(len(S) - n + 1):
r.append(S[i:i+n])
return r
s1 = 'paraparaparadise'
s2 = 'paragraph'
st1 = set(ngram(s1, 2))
st2 = set(ngram(s2, 2))
print(st1 | st2)
print(st1 & st2)
print(st1 - st2)
print('se' in st1)
print('se' in st2)

bi-gramを作るために先ほどのn-gramを使いまわします。pythonの集合演算について理解しておけば問題ないでしょう。

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

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

1
2
3
4
5
6
def temperature(x,y,z):
return str(x)+'時の'+str(y)+'は'+str(z)
x = 12
y = '気温'
z = 22.4
print (temperature(x,y,z))

入力を結合するだけです。strを利用して文字列に変換するのを忘れずに。

08. 暗号文

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

- 英小文字ならば(219 - 文字コード)の文字に置換

- その他の文字はそのまま出力

この関数を用い,英語のメッセージを暗号化・復号化せよ.

1
2
3
4
5
6
7
8
9
10
11
12
13
def cipher(S):
new = []
for s in S:
if 97 <= ord(s) <= 122:
s = chr(219 - ord(s))
new.append(s)
return ''.join(new)

s = 'I am an NLPer'
new = cipher(s)
print (new)

print (cipher(new))

ordはpythonの組み込み関数で、Unicodeコードポイントを表す整数を返します。chrはその逆で、整数を受け取り文字を返します。

97aを、122zを表します。

つまり、文字をordで整数に変換し、219から引いてchrに戻すということは以下のような変換を行なっていることになるのです。

この変換を再び行うと元の文字に戻ることがわかると思います。

1
2
3
4
a -> z
b -> y
...
z -> a

09. Typoglycemia

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

1
2
3
4
5
6
7
8
9
10
11
12
13
import random
s = 'I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .'
ans = []
text = s.split()
for word in text:
if (len(word)>4):
mid = list(word[1:-1])
random.shuffle(mid)
word = word[0] + ''.join(mid) + word[-1]
ans.append(word)
else:
ans.append(word)
print (' '.join(ans))

ランダムに並び変えるために、標準ライブラリrandomを使うと良いでしょう。

最後に

全100問の解説に戻る

記事情報

  • 投稿日:2020年5月9日
  • 最終更新日:2020年5月9日