Port 53

明日のための技術メモ

言語処理100本ノック 2020 第1章 後半

nlp100.github.io

第1章 準備運動の後半(05-09まで)解説を書きます。
早速05からがヤマだと思った。個人の感想です。

第1章前半はこちら

目次

05. n-gram

f:id:saturn-glave:20200429115442p:plain

n-gramって何だし、と思ったのでまず解説記事を調べる。
テキストの分割方法の一種とのこと。いよいよ言語処理っぽくなってきた。
文字単位で区切るのと、単語単位で区切る方法があり、
ポイントとしては基準になる1文字目(1単語目)をずらしながらn文字数えることだった。

参考記事

qiita.com

解答

# coding:utf-8


def n_gram(num, sentence):
    ans = []
    for i in range(len(sentence)):
        ans.append(sentence[i:i + num])
    return(ans)


def main():
    s = "I am an NLPer"
    w = s.split()
    print("文字単位n-gram")
    print(n_gram(2, s))
    print("単語単位n-gram")
    print(n_gram(2, w))


if __name__ == "__main__":
    main()

06. 集合

f:id:saturn-glave:20200429120606p:plain

みんな大好きsetの出番。超便利なので積極的に使っていきたい。
和集合・差集合・積集合の書き方はさらっと書けるので覚えておく。

ポイント

  • 和集合 x | y
  • 差集合 x - y
  • 積集合 x & y

解答

# coding:utf-8


def n_gram(num, sentence):
    ans = []
    for i in range(len(sentence)):
        ans.append(sentence[i:i + num])
    return(ans)


def is_se(sentence):
    if 'se' in sentence:
        return True
    return False


def main():
    s1 = "paraparaparadise"
    s2 = "paragraph"

    x = set(n_gram(2, s1))
    y = set(n_gram(2, s2))
    print('X')
    print(x)
    print('Y')
    print(y)

    print("和集合")
    print(x | y)
    print("積集合")
    print(x & y)
    print("差集合")
    print(x - y)

    print('x: ', is_se(x))
    print('y: ', is_se(y))


if __name__ == "__main__":
    main()

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

f:id:saturn-glave:20200429121045p:plain

プログラム実行に引数がほしい時、argpaseを使う。

参考記事

docs.python.org

解答

# coding:utf-8
import argparse


def arg():
    parser = argparse.ArgumentParser(description='x時のyはz 引数3つ')
    parser.add_argument('x', help='num')
    parser.add_argument('y', help='string')
    parser.add_argument('z', help='num')

    args = parser.parse_args()
    ans = args.x + '時の' + args.y + 'は' + args.z

    return(ans)


def main():
    print(arg())


if __name__ == "__main__":
    main()

08. 暗号文

f:id:saturn-glave:20200429121212p:plain

CTFでお世話になっている chrordはもちろん、
今回は小文字判定があるので、islower()を使う。

参考記事

note.nkmk.me

解答

# coding:utf-8


def cipher(letter):
    ans = ''
    for l in letter:
        if l.islower():
            ans += chr(219 - ord(l))
        else:
            ans += l
    return ans


def main():
    s = input()
    print(cipher(s))


if __name__ == "__main__":
    main()

09. Typoglycemia

f:id:saturn-glave:20200429121240p:plain

途中文字列を切り出してシャッフルが必要。
しかし、Pythonの場合文字列はimmutableなので、
リストをランダムソートする関数と別の関数を使わないといけない。

ポイント

  • 文字列・タプルをシャッフル、シャッフルされたリストを新規作成する時は random.sample()
  • リストをランダムソートする時は random.shuffle()

参考記事

note.nkmk.me

解答

# coding:utf-8
import random

s = "I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
ans = ''

for item in s.split():
    if len(item) <= 4:
        ans += item
    else:
        tmp = ''.join(random.sample(item[1:-1], len(item) - 2))
        ans += item[0] + tmp + item[-1]
    ans += ' '

print(ans)