それでは毛玉諸君、これにて失敬

日々の精進を備忘録的に綴ります。

言語処理100本ノック 2020 【第1章】

親知らずを抜いたら血が止まらなくなりました。ko_ya346です。
言語処理100本ノック2020(Rev 2)を始めたので解法をまとめていきます。

00. 文字列の逆順

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

s = "stressed"
print(s[::-1])

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

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

s = "パタトクカシーー"
print(s[::2])

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

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

s1 = "パトカー"
s2 = "タクシー"
s = ""

"".join([s1[i]+s2[i] for i in range(4)])

03. 円周率

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

s = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
sl = s.replace(",", "").replace(".", "").split(" ")
print([len(v) for v in sl])

複数のreplaceをまとめて実行する方法ってないんですかね?

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

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

05. n-gram

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

def ngram(lst, n):
    return [lst[i:i+n] for i in range(len(lst)-n+1)]

s = "I am an NLPer"
tango = s.split(" ")
print(ngram(tango, 2))

moji = s.replace(" ", "")
print(ngram(moji, 2))

06. 集合

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

import numpy as np

s1 = "paraparaparadise"
s2 = "paragraph"
x = ngram(s1, 2)
y = ngram(s2, 2)
print(x, y)
print(np.union1d(x, y))
print(np.intersect1d(x, y))
print(np.setdiff1d(x, y))
print("se" in x)
print("se" in y)

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

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

def xyz(x, y, z):
    return f"{x}時の{y}は{z}"

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

08. 暗号文

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

英小文字ならば(219 - 文字コード)の文字に置換
その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.

import re


def cipher(sl):
    ret = ""
    for s in sl:
        if re.match("[a-z]", s):
            ret += str(219-ord(s))
        else:
            ret += s
    return ret

s = "iamsuperman"
cipher(s)

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


def typoglycemia(sl):
    for i in range(len(sl)):
        if len(sl[i])<=4:
            continue
        sl[i] = sl[i][0] + "".join(random.sample(sl[i][1:-1], len(sl[i][1:-1]))) + sl[i][-1]
    return sl

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

実は去年の夏ごろにも挑戦しましたが第4章あたりで断念してしまいました。
今回は頑張って完走したいと思います。