言語処理100本ノック(第1章)
いつしか途中で投げてたから最初からやってみる
言語はpython3.6
参考にした問題
第1章: 準備運動
00. 文字列の逆順
文字列"stressed"の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.
In [1]: "stressed"[::-1] Out[1]: 'desserts'
01. 「パタトクカシーー」
「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.
In [2]: "パタトクカシーー"[::2] Out[2]: 'パトカー'
02. 「パトカー」+「タクシー」=「パタトクカシーー」
「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.
In [3]: "".join([i[0]+i[1] for i in zip("パトカー", "タクシー")]) Out[3]: 'パタトクカシーー'
03. 円周率
"Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.
In [8]: import re In [9]: words = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.".split() In [10]: [len(re.findall(r'[a-zA-Z]', word)) for word in words] Out[10]: [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]
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文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
In [17]: words = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.".split() In [18]: elem_dict = {} In [19]: for i, word in enumerate(words, 1): ...: elem_dict[i] = word[:1] if i in [1, 5, 6, 7, 8, 9, 15, 16, 19] else word[:2] In [20]: print(elem_dict) {1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O', 9: 'F', 10: 'Ne', 11: 'Na', 12: 'Mi', 13: 'Al', 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 18: 'Ar', 19: 'K', 20: 'Ca'}
05. n-gram
与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,"I am an NLPer"という文から単語bi-gram,文字bi-gramを得よ.
In [35]: def ngram(seq, unit): ...: return [seq[i: i+unit] for i in range(0, len(seq) - 1)] In [36]: word = "I am an NLPer" In [37]: ngram(word.split(), 2) Out[37]: [['I', 'am'], ['am', 'an'], ['an', 'NLPer']] In [38]: ngram(word, 2) Out[38]: ['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
06. 集合
"paraparaparadise"と"paragraph"に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,'se'というbi-gramがXおよびYに含まれるかどうかを調べよ.
In [47]: x = ngram("paraparaparadise", 2) In [48]: y = ngram("paragraph", 2) # 和集合 In [49]: set(x+y) Out[49]: {'ad', 'ag', 'ap', 'ar', 'di', 'gr', 'is', 'pa', 'ph', 'ra', 'se'} # 積集合 In [50]: set(x) & set(y) Out[50]: {'ap', 'ar', 'pa', 'ra'} # 差集合 In [51]: set(x) - set(y) Out[51]: {'ad', 'di', 'is', 'se'} In [52]: "se" in x Out[52]: True In [53]: "se" in y Out[53]: False
07. テンプレートによる文生成
引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y="気温", z=22.4として,実行結果を確認せよ.
In [54]: f = lambda x, y, z: f"{x}時の{y}は{z}" In [55]: f(x=12, y="気温", z=22.4) Out[55]: '12時の気温は22.4'
08. 暗号文
与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
英小文字ならば(219 - 文字コード)の文字に置換
その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ
In [65]: def cipher(msg): ...: c_msg = "" ...: for m in msg: ...: c_msg += chr(219 - ord(m)) if m in "abcdefghijklmnopqrstuvwxyz" else m ...: return c_msg In [66]: cipher("hello world!") Out[66]: 'svool dliow!' In [67]: cipher("svool dliow!") Out[67]: 'hello world!'
09. Typoglycemia
スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind .")を与え,その実行結果を確認せよ.
In [78]: def typoglycemia(msg): ...: typo_msg_list = [] ...: for word in msg.split(): ...: if len(word) <= 4: ...: typo_msg_list += [word] ...: else: ...: typo_msg_list += [word[:1] + "".join(random.sample(word[1: -1], len(word[1: -1]))) + word[::-1][:1]] ...: return " ".join(typo_msg_list) In [79]: msg = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ." In [80]: typoglycemia(msg) Out[80]: "I cdun'olt beilvee that I cuold acuallty usrtandend what I was rienadg : the pnmahenoel pweor of the hmaun mind ."
準備運動なのにやや苦戦
うーん、当時面倒で投げた理由はこれか
今回は全部やる
負けない、投げ出さない、逃げ出さない