【言語処理100本ノック】課題No.06〜09

業務で自然言語処理(NLP)に取り組む予定なので、自然言語処理の練習として東北大学の乾・鈴木研究室さんの『言語処理100本ノック 2015』に取り組みたいと思います。

www.cl.ecei.tohoku.ac.jp

今回の記事では、第1章「06.集合〜09.Typoglycemia」に取り組みます。 間違いや改善点等がありましたら、ご指摘下さい。

また、解くために調べたサイトも記載しておきます。 (サイトの内容は、特にまとめておりません。)

06.集合

課題

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

解答

get_ngramは、前回の記事の「05.n-gram」を参考にして下さい。 set型の集合演算を利用して、和集合,積集合,差集合を求めました。

#05.n-gram参照
def get_ngram(seq, num):
    result = [seq[index:index+num] for index in range(len(seq)+1-num)]
    return result
 
if __name__ == '__main__':
    #06. 集合
    target_X = "paraparaparadise"
    target_Y = "paragraph"
 
    #文字bi-gramの集合
    num = 2
    X = set(get_ngram(target_X, num))
    Y = set(get_ngram(target_Y, num))
 
    #和集合
    union_XY = X | Y
    union_XY = X.union(Y)
    #{'ad', 'ag', 'ap', 'ar', 'di', 'gr', 'is', 'pa', 'ph', 'ra', 'se'}
 
    #差集合
    diff_XY = X - Y
    diff_XY = X.difference(Y)
    #{'ad', 'di', 'is', 'se'}
 
    #積集合
    inter_XY = X & Y
    inter_XY = X.intersection(Y)
    #{'ap', 'ar', 'pa', 'ra'}
 
    #'se'の有無
    target_char = 'se'
    havingChar_X = target_char in X #True
    havingChar_Y = target_char in Y #False

set型で集合演算

以下のサイトに詳しく書いてあるので、確認して下さい。

note.nkmk.me

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

課題

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

解答

文字列の結合を利用して、関数を実装しました。

def generate_tempSentence(x,y,z):
    result = str(x) + '時の' + str(y) + 'は' + str(z)
    return result
 
if __name__ == '__main__':
    #07.テンプレートによる文生成
    (x, y, z) = (12, "気温", 22.4)
    generate_tempSentence(x, y, z) #'12時の気温は22.4'

08.暗号文

課題

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

  • 英小文字ならば(219 - 文字コード)の文字に置換
  • その他の文字はそのまま出力

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

解答

def cliper(str):
    result = [chr(219-ord(char)) if char.isalpha() and char.islower() else char for char in str]
    result = ''.join(result)
    return result
 
if __name__ == '__main__':
    #08.暗号文
    a = cliper('taaka11111') #'gzzpz11111'
    b = cliper(a) #'taaka11111'

英数字文字列の判定方法

以下のサイトに詳しく書いてあるので、確認して下さい。

文字コード

文字コード、全然知らなかったです…

当然ですが、全角・半角で違う文字コードが付与されています。

文字 文字コード 全角/半角
a 97 半角
z 122 半角
65345 全角
65370 全角

以下のサイトに詳しく書いてあるので、確認して下さい。

tanishiking24.hatenablog.com

09.Typoglycemia

課題

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

解答

リストをシャッフルするメソッドは、表にあるように2つあります。 今回は、文字列に対応して、元リストを変化させないrandom.sampleを利用して、解答しました。

メソッド名 文字列に対応 破壊的/非破壊的
random.shuffle × 破壊的
random.sample 非破壊的
#09. Typoglycemia
target = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
 
random.seed(1)
wordList = target.split(' ')
result = ' '.join([word[0] + ''.join(random.sample(word[1:-1], len(word[1:-1]))) + word[-1] if len(word) > 4 else word for word in wordList])
#I cuno'dlt bevilee that I could aalcutly ursnetnadd what I was rianedg : the paomenhnel pwoer of the haumn mind .

リストをシャッフル

以下のサイトに詳しく書いてあるので、確認して下さい。

www.headboost.jp