自然言語処理100本ノック
準備運動の続きです。
解説動画はこちら
自然言語処理100本ノックはこちら
自然言語処理100本ノック
前回はこちら
準備運動1
さて
続きですが
06. 集合
"paraparaparadise"と"paragraph"に含まれる
文字bi-gramの集合を, それぞれ, XとYとして求め,
XとYの和集合,積集合,差集合を求めよ.
さらに,'se'というbi-gramが
XおよびYに含まれるかどうかを調べよ.
文字列の集合を考える問題です。
bi-gramというのはふた文字の組み合わせです。
前回作成したn-gramを作る関数を
用いてbi-gramを作っていきます。
set型は重複を排除したデータ構造です。
リスト型からset関数で作成できるので
bi-gramの結果をそのままsetにします。
先頭から二文字ずつ切り取った文字を
集合にしているので重複した部分は
取り除かれます。
Pythonの集合の型同士で
そのまま計算ができます。
和集合、積集合、差集合
文字を含むかどうかの判定は
以下のようなコードになります。
07. テンプレートによる文生成
引数x, y, zを受け取り「x時のyはz」という
文字列を返す関数を実装せよ.
さらに,x=12, y="気温", z=22.4として,
実行結果を確認せよ.
恐らくですが
気温を英語に直すと
temperature
なので
template
とかけているんじゃ無いかと!!!!
素敵すぎる問題です。
嫌いじゃ無い、こういうの
ということで
Pythonでは文字列のformatで
文字の差込ができます。
メールの定型文など
文字の差し込みをする際に非常に便利で
業務でも多用します。
formatは覚えておくと
非常に重宝しますね。
08. 暗号文
与えられた文字列の各文字を,
以下の仕様で変換する関数cipherを実装せよ.
・英小文字ならば(219 - 文字コード)の文字に置換
・その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.
まずは英小文字かどうかを
判定するという部分です。
これは非常に厄介で
Pythonでは文字列型にそれっぽい関数があるのですが
うまく判定されないという致命的な欠陥があります。
なので判定関数を先に作ります。
reライブラリを用いて
正規表現で英小文字を判定します。
この関数を用いると英小文字以外はFalseになります。
この判定結果を用いて
暗号文を作成する関数を作ります。
英小文字の際は
条件として
(219 - 文字コード)の文字に置換
というのがあります。
文字というのは
全て文字番号が存在し
一文字ずつ番号が降られています。
Pythonでは
ord(文字列)
で文字番号を取得できます。
chr(番号)
で文字を取得できます。
組み合わせると文字を
変換できるというわけです。
最終的にできた関数はこちら。
関数の結果は文字が暗号化され
その結果をもう一度関数にかけると
元の文字に復号されます。
09. Typoglycemia
スペースで区切られた単語列に対して,
各単語の先頭と末尾の文字は残し,
それ以外の文字の順序を
ランダムに並び替えるプログラムを作成せよ.
ただし,長さが4以下の単語は並び替えないこととする.
適当な英語の文(例えば
"I couldn't believe that I could actually understand
what I was reading :
the phenomenal power of the human mind ." )
を与え,その実行結果を確認せよ.
これは非常に厄介な問題ですね
考え方はいくつもあり
答えは一つにならないと思いますが
自分のコードはこうなりました。
実行毎に文字の順番は入れ替わります。
この場合の考え方としては
元の文章の四文字以下はそのままに
五文字以上は空白にしたデータを用意します。
別途五文字以上のものをリストに確保します。
元の文章の空白部分に
ランダムに並び替えしたリストを
順番に差し込んでいます。
もう少しスマートに書けるかなと思います
リファクタリングは大事ですね。
さて
これで準備運動は終わりです。
これで
準備運動ですからねー
なかなかパズルのようで
面白いですよね。
続きはまた
それでは。
準備運動の続きです。
解説動画はこちら
自然言語処理100本ノックはこちら
自然言語処理100本ノック
前回はこちら
準備運動1
さて
続きですが
06. 集合
"paraparaparadise"と"paragraph"に含まれる
文字bi-gramの集合を, それぞれ, XとYとして求め,
XとYの和集合,積集合,差集合を求めよ.
さらに,'se'というbi-gramが
XおよびYに含まれるかどうかを調べよ.
文字列の集合を考える問題です。
bi-gramというのはふた文字の組み合わせです。
前回作成したn-gramを作る関数を
用いてbi-gramを作っていきます。
def n_gram(st, n): return [st[i:i+n] for i in range(len(st)-n+1)]pythonでは集合を表現するデータ型があります。
set型は重複を排除したデータ構造です。
リスト型からset関数で作成できるので
bi-gramの結果をそのままsetにします。
X = set(n_gram("paraparaparadise",2)) Y = set(n_gram("paragraph",2)) print(X) print(Y)
{'ap', 'ad', 'di', 'ra', 'is', 'ar', 'pa', 'se'} {'ap', 'ph', 'ra', 'ar', 'pa', 'ag', 'gr'}
先頭から二文字ずつ切り取った文字を
集合にしているので重複した部分は
取り除かれます。
Pythonの集合の型同士で
そのまま計算ができます。
和集合、積集合、差集合
文字を含むかどうかの判定は
以下のようなコードになります。
# 和集合 | union print(X|Y) # 積集合 & intersection print(X&Y) # 差集合 - difference print(X-Y) # 含まれるかどうか in print('se' in X) print('se' in Y)
{'ap', 'ad', 'di', 'ra', 'ph', 'is', 'ar', 'pa', 'ag', 'gr', 'se'} {'pa', 'ap', 'ar', 'ra'} {'is', 'ad', 'se', 'di'} True False
07. テンプレートによる文生成
引数x, y, zを受け取り「x時のyはz」という
文字列を返す関数を実装せよ.
さらに,x=12, y="気温", z=22.4として,
実行結果を確認せよ.
恐らくですが
気温を英語に直すと
temperature
なので
template
とかけているんじゃ無いかと!!!!
素敵すぎる問題です。
嫌いじゃ無い、こういうの
ということで
Pythonでは文字列のformatで
文字の差込ができます。
def temperature(x,y,z): return '{0}時の{1}は{2}'.format(x,y,z) temperature(x=12, y="気温", z=22.4)
'12時の気温は22.4'
メールの定型文など
文字の差し込みをする際に非常に便利で
業務でも多用します。
formatは覚えておくと
非常に重宝しますね。
08. 暗号文
与えられた文字列の各文字を,
以下の仕様で変換する関数cipherを実装せよ.
・英小文字ならば(219 - 文字コード)の文字に置換
・その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.
まずは英小文字かどうかを
判定するという部分です。
これは非常に厄介で
Pythonでは文字列型にそれっぽい関数があるのですが
うまく判定されないという致命的な欠陥があります。
なので判定関数を先に作ります。
reライブラリを用いて
正規表現で英小文字を判定します。
import re def isalpha(st): return re.compile(r'^[a-z]+$').match(st) is not None
この関数を用いると英小文字以外はFalseになります。
この判定結果を用いて
暗号文を作成する関数を作ります。
英小文字の際は
条件として
(219 - 文字コード)の文字に置換
というのがあります。
文字というのは
全て文字番号が存在し
一文字ずつ番号が降られています。
Pythonでは
ord(文字列)
で文字番号を取得できます。
chr(番号)
で文字を取得できます。
組み合わせると文字を
変換できるというわけです。
最終的にできた関数はこちら。
def cipher(st): return ''.join([chr(219-ord(s)) if isalpha(s) else s for s in st]) message = '私の名前は乙pyです' #暗号化 cipher_text = cipher(message) print(cipher_text) #復号化 print(cipher(cipher_text))
私の名前は乙kbです 私の名前は乙pyです
関数の結果は文字が暗号化され
その結果をもう一度関数にかけると
元の文字に復号されます。
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 w = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ." def typoglycemia(w): ws = w.split(' ') start,end=ws[0],ws[-1] base = ['' if len(a)>4 else a for a in ws[1:-1]] tmp = [a for a in ws[1:-1] if len(a)>4] random.shuffle(tmp) result,c = [start],0 for b in base: if b=='': result.append(tmp[c]) c+=1 else: result.append(b) return result + [end] print(typoglycemia(w))
['I', 'power', 'actually', 'that', 'I', "couldn't", 'reading', 'believe', 'what', 'I', 'was', 'human', ':', 'the', 'understand', 'phenomenal', 'of', 'the', 'could', 'mind', '.']
実行毎に文字の順番は入れ替わります。
この場合の考え方としては
元の文章の四文字以下はそのままに
五文字以上は空白にしたデータを用意します。
別途五文字以上のものをリストに確保します。
元の文章の空白部分に
ランダムに並び替えしたリストを
順番に差し込んでいます。
もう少しスマートに書けるかなと思います
リファクタリングは大事ですね。
さて
これで準備運動は終わりです。
これで
準備運動ですからねー
なかなかパズルのようで
面白いですよね。
続きはまた
それでは。
コメントする