For Your ISHIO Blog

データ分析や機械学習やスクラムや組織とか、色々つぶやくブログです。

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

思い立ったので言語処理100本ノックをやっていきます。

www.cl.ecei.tohoku.ac.jp

「第1章: 準備運動」をやりました。テキストや文字列を扱う題材に取り組みながら、プログラミング言語のやや高度なトピックを復習します。

環境

  • python3系
  • Colaboratory上で実施

00. 文字列の逆順

文字列"stressed"の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.

string = "stressed"

print("先頭から: " + string)
print("末尾から: " + string[::-1])

01. 「パタトクカシーー」

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

string = "パタトクカシーー"
output = string[0] + string[2] + string[4] + string[7]
print(output)

02. 「パトカー」+「タクシー」=「パタトクカシーー」

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

string1 = "パトカー"
string2 = "タクシー"
word_list = []

for p, t in zip(string1, string2):
  word_list.append(p)
  word_list.append(t)
output = "".join(word_list)
print(output)

03. 円周率

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

text = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
output = [w[0] for w in text.split()]
print(output)

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

dic = {}
text = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
word_list = text.split()
for i, word in enumerate(word_list):
  w = word.strip(".")
  if i+1 in [1, 5, 6, 7, 8, 9, 15, 16, 19]:
    dic[w[0]] = w
  else:
    dic[w[0:2]] = w
print(dic)

05. n-gram

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

def generate_ngram(sequence, n):
  if isinstance(sequence, str):
    sequence = sequence.replace(" ", "")
  n_gram_list = []  
  for i in range(len(sequence)):
    if i + n <= len(sequence):  
      n_gram_list.append(sequence[i: i+n])
  return n_gram_list

text = "I am an NLPer"
word_list = text.split()
n = 2

# 単語bi-gram
print("単語bi-gram")
print(generate_ngram(word_list, n))

# 文字bi-gram
print("文字bi-gram")
print(generate_ngram(text, n))

06. 集合

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

x = "paraparaparadise"
y = "paragraph"

bi_gram_x = generate_ngram(x, n=2)
bi_gram_y = generate_ngram(y, n=2)
print("bi_gram_x: ", set(bi_gram_x))

print("bi_gram_y: ", set(bi_gram_y))

# 和集合
print("和集合: ", set(bi_gram_x) | set(bi_gram_y))

# 積集合
print("積集合: ", set(bi_gram_x) & set(bi_gram_y) )

# 差集合
print("差集合 x - y: ", set(bi_gram_x) - set(bi_gram_y) )
print("差集合 y - x: ", set(bi_gram_y) - set(bi_gram_x) )

# 'se'というbi-gramがXおよびYに含まれるかどうか
print("'se' in bi_gram_x: ", "se" in set(bi_gram_x))
print("'se' in bi_gram_y: ", "se" in set(bi_gram_y))

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

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

def generate_templete(x, y, z):
  templete_text = "{}時の{}は{}".format(x, y, z)
  return templete_text

x = 12
y = "気温"
z = 22.4
print(generate_templete(x, y, z))

08. 暗号文

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

  • 英小文字ならば(219 - 文字コード)の文字に置換
  • その他の文字はそのまま出力 この関数を用い,英語のメッセージを暗号化・復号化せよ.
def cipher(string):
  cipher_list = []
  for s in string:
    if s.islower():
      cipher_list.append(chr(219 - ord(s)))
    else:
      cipher_list.append(s)
  return "".join(cipher_list)

sequence = "It's a little bit funny, this feeling inside. I'm not one of those who can easily hide."
encryption = cipher(sequence)
decryption = cipher(encryption)

print("英語のメッセージ: ", sequence)
print("暗号化: ", encryption)
print("復号化: ", decryption)

09. Typoglycemia

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

def typoglycemia(text):
  typoglycemia_list = []
  word_list = text.split()
  
  for word in word_list:
    if len(word) <= 4:
      typoglycemia_list.append(word)
    else:
      midle = word[1:-1]
      random_midle = "".join(random.sample(midle, len(midle)))
      new_word = word[0] + random_midle + word[-1]
      typoglycemia_list.append(new_word)

  return " ".join(typoglycemia_list)

text = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
print(typoglycemia(text))

以上です。正解かはわかりません。また、次の章をやったら載せます。