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

この夏休みはPython言語処理100本ノックを解いていきます。このブログは自分用の備忘録です。夏休みが終わるまでに1周したいです。当方プログラミング初心者のB3です。何か変なところがあったら教えて頂けると幸いです。

 

00.stressedの文字列を逆順で表示せよ

スライス:リスト名[開始値:停止値:間隔]

この構文によって、リストの要素を操作することができる。開始値に何も入れないと最初の要素、停止値に何も入れないと最後の要素、間隔に何も入れないと1が設定される。間隔が2だと1つ飛ばし、-1だと逆順になる。

text = 'stressed'
print(text[::-1])

 

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

上と同様に、スライスを使って1つ飛ばしに要素を抽出すればOK。

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

 

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

両方の文字列から空の文字列に1文字ずつ加えていって、それをfor文で繰り返せば良い。Pythonのfor文はrange関数でインデックスの数を指定するだけでも使えるから楽ちん。

text_a = 'パトカー'
text_b = 'タクシー'
ans = ''

for i in range(len(text_a)):
 ans += text_a[i]
 ans += text_b[i]

print(ans)

 

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

解き方の方針としては、①split関数で単語レベルに分割したリストを得て、②リストの各要素の文字数をlenで数えて新しいリストに格納する。この2段階で終えることができそう。

ただし、まず余計なコンマやピリオドを抜く必要があるので(そうしないと②でコンマピリオドも文字数に数えられてしまう)、①の前にreplace関数で文に下拵えを行う必要がある。

text = 'Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.'
text = text.replace(',','').replace('.','') #コンマとピリオドをスペースに変換
ans =
for i in range(len(text.split())):
ans.append(len(text.split()[i]))
print(ans)

 

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

先ほどと同様に、まずはsplit関数で文を単語レベルに分割して、単語のリストを得る。今回は最初の1 or 2文字を抽出するだけなので、コンマやピリオドを抜く必要はない。

次に空の辞書ans{}を用意しておいて、その中に単語の一部(1文字 or 2文字)とインデックスナンバーをセットで格納していく。

for文でリストの要素とインデックスを同時に取得するためには、enumerate関数を使う。

【enumerate関数の使用例】

city = ['tokyo', 'nagoya','kyoto']
for i,j in enumerate(city):
print(i,j) #iがインデックス、jが要素

<実行結果>

0 tokyo
1 nagoya
2 kyoto

このように、iでインデックスを、jで要素の中身を取得することができる。

辞書にない要素を追加する際、辞書名[キー] = 値 と書けばよい(参考記事)。その前に、指定された番目の配列を作っておく必要がある。これによって、辞書に要素を追加するためのfor文の中で、i(インデックス)に1を加えた数がその番目の要素のいずれかに一致したら1文字をキーに追加、しなかったら2文字をキーに追加するという条件分岐ができるようになる。

キーに追加する文字数の指定、つまりキーの停止値を指定するためには、最初に解いた00の要領で、[キー[:停止値]]とすれば良い。なお、ここで停止値そのものはキーには含まれないので、表示させたいキーのインデックスり1つ足した数を停止値に指定しないといけない。

text = 'Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.'
ans = {}
one = [1, 5, 6, 7, 8, 9, 15, 16, 19]
for i,j in enumerate(text.split()):
if i+1 in one: #i+1番目がoneの中にある番目だったら
ans[j[:1]] = i+1 #1文字とそのiをansに加える
else:
ans[j[:2]] = i+1
print(ans)

 

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

n-gramとは、文字列をn文字 or n単語ずつ分割する方法。実際の例はこの記事を参照した。

例えば、「今日はいい天気ですね。」という文章の文字bi-gramを考える。その場合、先頭の文字を1つずつずらしながら2文字ずつのかたまりを抽出すると文字bi-gramを得られる。

文字bi-gram:'今日', '日は', 'はい', 'いい', 'い天', '天気', '気で', 'です', 'すね', 'ね。'

また、単語bi-gramの場合は、分割の単位を単語にすれば良い。一旦元の文を単語分割すると

'今日', 'は', '良い', '天気', 'です', 'ね。' ここから2単語ずつ取ってくれば単語bi-gramなので

単語bi-gram:'今日は', 'は良い', '良い天気', '天気です', 'ですね。'

この処理をプログラムで実装する方法を考える。まず、処理対象のリストlstと、n-gram化の処理を行なった結果を格納するための空のリストngramedを用意する。

for文でlstの長さ分だけngramedに要素(lst[i:i+n])を追加する処理を繰り返す。ここで注意したいのが、最後のngramedの要素の処理である。先程の「今日はいい天気ですね。」の最後の要素は「ね。」だったが、普通にlen(lst)回だけfor文を回してしまうと、最後の要素が「。」だけになってしまい、これはn-gramに含まれるべきではない。これを防ぐためには、i+nとlen(lst)を比較して、i+n>len(lst)となったときにfor文を抜けるようにすれば良い。

def ngram(lst,n):
ngramed =
for i in range(len(lst)):
if i+n <= len(lst): #最後にn未満の要素ができてしまうのを防ぐ
ngramed.append(lst[i:i+n]) #ngramedの末尾に、lstのi番目から(i+n)-1番目の要素を追加する
else:
break
return ngramed

text = 'I am a NLPer'
word = text.split()
text_bigram = ngram(text,2)
word_bigram = ngram(word,2)
print(text_bigram)
print(word_bigram)

 

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

前の問題と同じことをすれば良い。ある要素aがあるリストlstに入っているかを調べたい場合、print('a' in lst)でTrueかFalseを出力することができる。

def ngram(lst,n):
ngramed = []
for i in range(len(lst)):
if i+n <= len(lst): #最後にn未満の要素ができてしまうのを防ぐ
ngramed.append(lst[i:i+n]) #ngramedの末尾に、lstのi番目から(i+n)-1番目の要素を追加する
else:
break
return ngramed

text2 = 'paragraph'
#set関数で要素のダブりのないリストを得る
X = set(ngram(text1,2))
Y = set(ngram(text2,2))
print(X,Y) #XとYを出力
print(X|Y) #XとYの和集合
print(X&Y) #XとYの積集合
print(X-Y) #XとYの差集合(X-Y)
print(Y-X) #XとYの差集合(Y-X)
print('se' in X) #Xにseが含まれるかどうか
print('se' in Y) #Yにseが含まれるかどうか

 

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

yとその他の出力はstr型だがxとzがint型なので、xとzをあらかじめstr型に変換してから返す必要がある。こうしないと、returnの中で+の演算子を使った時に、「型の違うもの同士は足せないぜ!」と怒られる。

def state(time,text,temp):
return str(time) + '時の' + text + 'は' +str(temp)
print(state(12,'気温',22.4))