*Aya's Prelude*

大学院生のよしなごと

自然言語処理100本ノック Part1

mlp100本ノックやるぞ~~!!

やりたくね?という機運が高まったのでなんとなく始めた。
なんで始めたか書こうとしたらなんでかわからんくなった。そんな2019年春。
Part1ってなってるし続くと思うじゃん。
ブログにしようと思ったのがたまたまだから多分ブログには続かないんだな~~
サイトはこれ
ということでとりあえず10こやった。

Q0~Q10 準備運動

準備運動といってもきっとプログラムを普段書く人の準備運動だろうということで最初から気合い入れていくぞ~~!!

Q0 文字列の逆順

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

ぷよぐやむめっちゃやむ

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

実行結果

'desserts'

いやまじでスライスとかいうの使う機会なさすぎて忘れてたから仕様を完全に忘れてめっちゃ時間かかった。ウケる。

Q1 「パタトクカシーー」

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


ぷよぐやむ

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

上の実行結果

'パトカー'

ぷよぐやむ

print(a_1[1::2])

上の実行結果

'タクシー'

ここはさっきスライドの仕様思い出したからわかっちゃえば行けるなという気持ち

Q2 「パトカー」+「タクシー」=「パタトクカシーー」

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

ぷよぐやむ

a_21 = 'パトカー'
a_22 = 'タクシー'
result = ''
for x,y in zip(a_21,a_22):
  result += x+y  
print(result)

実行結果

パタトクカシーー

うんちなので空っぽの文字列どうやってつくるのとか言い出す
空は青い

Q3 円周率

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

実行結果

[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

これはreplace()が出てこなくてなんだっっけ~~ってやった

Q4 元素記号

"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文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
a_41 = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
a_42 = a_41.split( )

色々試してたやつ(だめだった)

one_frase = [0,4,5,6,7,8,14,18]
for i,(x,y) in enumerate(zip(a_42,one_frase)):
  print (i,x,y)

だめなやつの実行結果

0 Hi 0
1 He 4
2 Lied 5
3 Because 6
4 Boron 7
5 Could 8
6 Not 14
7 Oxidize 18

そっから集合にすればよくね?ってひらめいたやつ

one_frase = set(one_frase)
Element_symbol = {}
for i,x in enumerate(a_42):
  if i in one_frase:
    Element_symbol[i] = x[0]
  else :
    Element_symbol[i] = x[0:2] 

よさげっぽくね??プリントするぞい!!

print(Element_symbol)

実行結果

{0: 'H', 1: 'He', 2: 'Li', 3: 'Be', 4: 'B', 5: 'C', 6: 'N', 7: 'O', 8: 'F', 9: 'Ne', 10: 'Na', 11: 'Mi', 12: 'Al', 13: 'Si', 14: 'P', 15: 'Se', 16: 'Cl', 17: 'Ar', 18: 'K', 19: 'Ca'}

ここはなんか実験しながらこっちのがよさそ~~を繰り返してたらうまいこといってよかったなと思いました(小並感)
副産物としてenumeratezipを組合す方法を覚えたので良いとする。

Q5 n-gram

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

文字列やリストなどなんて言われたもんだからビビっちゃってどうやって型確認するんだっけって試してたやつ

a = []
b = ''
type(a)
list
type(b)
str

試すの終わり
ちなみにクソほどわからんくてどうすればいいんだ~~~~~~~うわ~~~~~~~って言いながら書いた。絶対こんなに書かなくていいやつ。つーか自分で書いてていやだ~~~~~~~~!!!!って叫びながら書いてた。

ぷよぐやむ

def n_gram(n,word,sent_or_word):

  # 単語n-gramなのか文字n-gramなのかで前処理変えなきゃ
  if sent_or_word == True:
    word = word.split( )
  
  # 色々変数おいとこ
  start = 0
  results = []
  hokan = ''

  # n-gramします
  for j in range(len(word)):
    result = []
    for i in range(start,n+start):
        if j >= len(word)-n+1:
          break
        result.append(word[i])
    if j >= len(word)-n+1:
          break
    results.append(result)
    start += 1
  if sent_or_word == False:
    word_n_grams = []
    words = ''
    for item in results:
      for k in item:
        words += k
      word_n_grams.append(words)
      words = ''
    results = word_n_grams
  return results
n_gram(2,"I am the bone of my sword.",True)
[['I', 'am'],
 ['am', 'the'],
 ['the', 'bone'],
 ['bone', 'of'],
 ['of', 'my'],
 ['my', 'sword.']]
a_5 = 'I am an NLPer'
n_gram(2,a_5,False)
['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']

先に感想書いちゃうくらいアホほど時間を使いました。
いやでも悩みながら書くのは楽しかったよ!

てか今気づいたけど3重ループじゃん草
なんとかしろよ

Q6 集合

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

ぷよぐやむ

a_61 = "paraparaparadise"
a_62 = "paragraph"
X = set(n_gram(2,a_61,False))
Y = set(n_gram(2,a_62,False))
print(X)
print(Y)

実行結果

{'ar', 'ap', 'di', 'se', 'ad', 'ra', 'pa', 'is'}
{'ag', 'gr', 'ph', 'ar', 'ap', 'ra', 'pa'}

それぞれのもろもろの集合とったやつ

print(X | Y)
print(X & Y)
print(X - Y)
print(Y - X)

実行結果

{'ad', 'ag', 'ap', 'ar', 'di', 'gr', 'is', 'pa', 'ph', 'ra', 'se'}
{'ap', 'ar', 'pa', 'ra'}
{'ad', 'di', 'is', 'se'}
{'ag', 'gr', 'ph'}

ほんでこれが集合にあるかどうか確かめるやつ

if 'se' in X:
  print(True)
else :
  print(False)
True
if 'se' in Y:
  print(True)
else :
  print(False)
False

これ関数にしたら書くの一回で済んだのでは????ウケてる

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

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

関数名と変数名がカスで有名

def make_sentence(num_1,word,num_2):
  print(num_1,'時の',word,"は",num_2)
make_sentence(12,'気温',22.4)

実行結果

12 時の 気温 は 22.4

急に難易度が下がった気がしてしまったが実は俺の気づいてないギミックがあったのかもしれない。

Q8 暗号文

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

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

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

ここもう問題が何言ってるのかわからんかったわなんだよ文字コードって
めっちゃ調べたわ

def cipher(sentence):
  pre = ''
  for char in sentence:
    if char.isupper() == False:
      pre += chr(219 - ord(char))
    else :
      pre += char
  
  return pre
text = "I am the bone of my sword Steel is my body and fire is my blood I have created over a thousand blades"
Code = cipher(text)
Decryption = cipher(Code)

これはまじで忘れそうなので調べたサイトをきちんと乗っけるとする
小文字と大文字の区別のために使ったサイト
文字コードってなんだよ!!ってなったときのサイト

暗号化した結果

print(Code)
I zn gsv ylmv lu nb hdliw Sgvvo rh nb ylwb zmw uriv rh nb yollw I szev xivzgvw levi z gslfhzmw yozwvh

復号化した結果

print(Decryption)
I am the bone of my sword Steel is my body and fire is my blood I have created over a thousand blades

Q9 Typoglycemia

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

最後の最後でまったくゆうことを聞かないタイプのポケモンなので例文は変えた

import random

def Typoglycemia(text):
  text = text.split( )

  results = ''
  
  for word in text:
    if len(word) <= 4:
      results += word + ' '
    else :
      sent = ''
      fi,la,mw = word[0],word[-1],list(word[1:-1])
      mws = random.sample(mw,len(mw))
      mwss = ''
      for k in mws:
        mwss += str(k)
      sent += fi + mwss + la + ' '
      results += sent
  return results
Typoglycemia(text)
'I am the bone of my sword Seetl is my body and fire is my bolod I have ceetard over a tunhosad belads '

書くの疲れたしもう言うことはない
しいていうならrandom.sampleの使い方かなぁ

今日のまとめ

思ったより考えたり書いたりするの楽しかった。
あと今日でめっちゃstr足せるじゃ~んってのとスライスだいぶ思い出せた。やってよかったな。

全体的な感想としては「へぇ~パズルかよ。」って感じだ。 楽しい。