整理と雑記

たまにリライト

Pythonで言語処理100本ノック(第1章: 準備運動)

Pythonの勉強のために言語処理100本ノックの問題を解いていく。今回は第1章。

www.cl.ecei.tohoku.ac.jp

00. 文字列の逆順

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

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

実行結果

desserts

参考:[python] スライスでリバース!!

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

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

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

実行結果

パトカー

参考:[python] スライスでリバース!!

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

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

pa = "パトカー"
ta = "タクシー"
pt = (p + t for p, t in zip(pa, ta))
print(''.join(pt))

実行結果

パタトクカシーー

参考:
* Python, zip関数の使い方: 複数のリストの要素をまとめて取得 | note.nkmk.me
* pythonの内包表記を少し詳しく
* 要素を区切り文字で連結 (str.join) | Python-izm

03. 円周率

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

import re

msg = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
length = [len(l) for l in (re.sub('[,.]', '', msg).split())]
print(length)

実行結果

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

参考:
* Python, splitでカンマ区切り文字列を分割、空白を削除しリスト化 | note.nkmk.me
* Pythonでの正規表現の使い方

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

import re

msg = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."

char_list = []
for i,v in enumerate(re.sub('[,.]', '', msg).split()):
    if i in [0, 4, 5, 6, 7, 8, 14, 15, 18]:
        char_list.append(v[:1])
    else:
        char_list.append(v[1:2])
print(char_list)

実行結果

['H', 'e', 'i', 'e', 'B', 'C', 'N', 'O', 'F', 'e', 'a', 'i', 'l', 'i', 'P', 'S', 'l', 'r', 'K', 'a']

参考:
* forループで便利な zip, enumerate関数 | Python Snippets
* Python, splitでカンマ区切り文字列を分割、空白を削除しリスト化 | note.nkmk.me
* Pythonでの正規表現の使い方

05. n-gram

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

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

msg = "I am an NLPer"
print(ngram(msg, 2))
print(ngram([word for word in msg.split()], 2))

実行結果

[('I', ' '), (' ', 'a'), ('a', 'm'), ('m', ' '), (' ', 'a'), ('a', 'n'), ('n', ' '), (' ', 'N'), ('N', 'L'), ('L', 'P'), ('P', 'e'), ('e', 'r')]
[('I', 'am'), ('am', 'an'), ('an', 'NLPer')]

参考:
* 【Python入門】リストとの違いは?タプルの使い方まとめ | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
* 【Python入門】range関数で繰り返し処理をする方法とは?
* [python] スライスでリバース!!

06. 集合

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

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

X_msg = "paraparaparadise"
Y_msg = "paragraph"
X = set(ngram(X_msg, 2))
Y = set(ngram(Y_msg, 2))

print(X|Y)
print(X-Y)
print(X&Y)
print(("s", "e") in X)
print(("s", "e") in Y)

実行結果

{('a', 'r'), ('a', 'g'), ('p', 'h'), ('a', 'd'), ('p', 'a'), ('a', 'p'), ('i', 's'), ('s', 'e'), ('g', 'r'), ('d', 'i'), ('r', 'a')}
{('i', 's'), ('a', 'd'), ('s', 'e'), ('d', 'i')}
{('a', 'r'), ('p', 'a'), ('r', 'a'), ('a', 'p')}
True
False

参考:
* Python, set型で集合演算(和集合、積集合や部分集合の判定など) | note.nkmk.me
* 【Python入門】リストとの違いは?タプルの使い方まとめ | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
* 【Python入門】range関数で繰り返し処理をする方法とは?
* [python] スライスでリバース!!

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

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

def msg(x, y, z):
    return "{0}時の{1}は{2}".format(x, y, z)

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

実行結果

12時の気温は22.4

参考:Python3での文字列フォーマットまとめ 旧型で生きるか、新型で生きるか

08. 暗号文

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

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

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

def cipher(input):
     return ''.join(chr(219-ord(s)) if s.islower() else s for s in input)

msg = "Hello World"
msg_cipher= cipher(msg)
print(msg)
print(msg_cipher)
print(cipher(msg_cipher))

実行結果

Hello World
Hvool Wliow
Hello World

参考:
* 文字→ascii。ascii→文字 ord, chr | Python Snippets
* Pythonで大文字・小文字を操作する文字列メソッド一覧 | note.nkmk.me

09. Typoglycemia

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

import re
import random

def shuffle(msg):
    shuffle_list =[]
    for s in msg.split():
        if len(s) > 4:
            first = s[0]
            middle = list(s[1:-1])
            last = s[-1]
            random.shuffle(middle)
            shuffle_list.append(s[0] + "".join(middle) + s[-1])
        else:
            shuffle_list.append(s)
    return " ".join(shuffle_list)

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

print(shuffle(msg))

実行結果(ランダムなのでその都度変わる)

I col'udnt bileeve that I cluod aactlluy udsnranted what I was rendiag : the pmnhaoenel pwoer of the huamn mind .

参考:乱数値の取得 | Python-izm