はじめに
今回は第1章の問題の後半部分No.5~No.9までを解いていきたいと思います.
第1章の問題の解き方を応用した問題などが出てきます.
自然言語処理について用語だけでも知っていると解きやすいと思います.(n-gramなど)
では,早速解いていきたいと思います.
05.n-gram
与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ.
コード
def word_bi_gram(text):
word_list = text.split()
bi_gram = [[word_list[i],word_list[i+1]] for i in range(0,len(word_list,)-1)]
return bi_gram
def str_bi_gram(text):
bi_gram = [[text[i],text[i+1]] for i in range(0,len(text)-1)]
return bi_gram
text= "I am an NLPer"
print(word_bi_gram(text))
print(str_bi_gram(text))
出力
[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
[['I', ' '], [' ', 'a'], ['a', 'm'], ['m', ' '], [' ', 'a'], ['a', 'n'], ['n', ' '], [' ', 'N'], ['N', 'L'], ['L', 'P'], ['P', 'e'], ['e', 'r']]
解説
n-gramとはn個ずつ文字を取得してくることを指し,今回はbi-gramなので二つずつ文字を取得することを指示されています.
また,関数を作成するように言われているので,defで関数を作っています.
処理自体は簡単で,受け取った文字列・リストに対して,その文字列・リスト長さ – 1回 のfor文を回し,二つずつ要素を取得すればbi-gramになります.
今回はn-gramの関数を作れとも読み取れるので下記にn-gramの関数も記載しておきます.
def n_gram(n, input):
n_gram = [input[i:i+n] for i in range(0,len(input)-n+1)]
return n_gram
text= "I am an NLPer"
word_list = text.split()
print(n_gram(2,word_list))
#[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
print(n_gram(2,text))
#['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に含まれるかどうかを調べよ.
コード
def n_gram(n, input):
n_gram = [input[i:i+n] for i in range(0,len(input)-n+1)]
return n_gram
word1 = "paraparaparadise"
word2 = "paragraph"
bi_gram1 = n_gram(2,word1)
bi_gram2 = n_gram(2,word2)
X = set(bi_gram1)
Y = set(bi_gram2)
print("Xの集合: ",X)
print("Yの集合: ",Y)
print("和集合: ",X|Y)
print("積集合: ",X&Y)
print("差集合: ",X-Y)
print("seが含まれているか: ", "se" in X|Y)
出力
Xの集合: {'di', 'ra', 'pa', 'se', 'is', 'ap', 'ad', 'ar'}
Yの集合: {'ra', 'ph', 'pa', 'gr', 'ap', 'ag', 'ar'}
和集合: {'di', 'ra', 'ph', 'pa', 'se', 'gr', 'is', 'ap', 'ag', 'ad', 'ar'}
積集合: {'ra', 'ap', 'ar', 'pa'}
差集合: {'di', 'ad', 'is', 'se'}
seが含まれているか: True
解説
文字列の集合に関する操作を学ぶ問題でしたね.
組み込み関数のsetの使い方を知っていれば解けるかがキーポイントです.
setの操作はこちらを参照するといいかと思います.
- 和集合はXまたはYの集合
- 積集合はXとYのandの集合
- 差集合はXからYの要素を取り除いた集合
07.テンプレートによる文生成
引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ.
コード
def template(x,y,z):
return "{}時の{}は{}".format(x,y,z)
x = 12
y = "気温"
z=22.4
print(template(x,y,z))
出力
12時の気温は22.4
解説
文字列の穴埋めに関する問題でしたね.
formatメソッドは{}の部分を適当なものに置き換えてくれます.
今回は順番に入れればよかったので,順番の指定する必要もなくそのまま置換すれば良いです.
08.暗号文
与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
- 英小文字ならば(219 – 文字コード)の文字に置換
- その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.
コード
def cipher(input):
output = ""
for s in input:
if s.islower():
output += chr(219-ord(s))
else:
output += s
return output
input = "ABC abc 123"
ans = cipher(input)
print(ans)
出力
ABC zyx 123
解説
alphabetをn個ずらすというような暗号化方式を作成する問題でした.
ord() は対象の文字をunicode化し,chr()はその逆の動きをしてくれます.
組み込み関数を知っていれば簡単に解ける問題でしたね.
import math
print(math.pi)
#3.141592653589793
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
text = "I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
word_list = text.split()
for i,word in enumerate(word_list):
if len(word) <= 4:
continue
start = word[0]
end = word[-1]
middle_list = list(word[1:-1])
random.shuffle(middle_list)
word_list[i] = start+"".join(middle_list)+end
print("変更前: ", text)
print("変更後: ", " ".join(word_list))
出力
変更前: I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .
変更後: I clu’nodt bileeve that I could allautcy urdtnaensd what I was rdianeg : the panmoeehnl poewr of the hamun mind .
解説
ランダムに文字列を並び替えるということができれば簡単な問題でしたね.
この問題のキーは組み込み関数のrandomのshuffleを知っていたかどうかだと思います.
ここまでの問題で文字列の操作はしてきているので,
文字列をリスト化→shuffle→リスト化の解除
ができてば問題なく解けたかと思います.
終わりに
今回は言語処理100本ノック第1章の05~09までの問題を解きました.
問題が単純な文字列操作から一捻りある形に変わってきましたね.
まだまだ組み込み関数を知っているか否かで解ける問題がほとんどですが,徐々に難しくなっていってるように感じます.
では,次回の第2章編でお会いしましょう.
次の記事
前の記事
コメント