第1章: 準備運動¶

00. パタトクカシーー¶

2つの文字列「パトカー」と「タクシー」の文字を先頭から交互に連結し、文字列「パタトクカシーー」を得よ。

In [21]:
a = 'パトカー'
b = 'タクシー'

result = ''
for i in range(0,4):
    result += a[i] + b[i]

print(result)
パタトクカシーー

01. タクシー¶

文字列「パタトクカシーー」の2, 4, 6, 8文字目を取り出し、それらを連結した文字列を得よ。

In [22]:
s = 'パタトクカシーー'
result = ''
for i in range(0, len(s), 2):
    result += s[i]
print(result)
パトカー

02. 文字列の逆順¶

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

In [23]:
s = "stressed"
res = s[-1:0:-1]
print(res)
dessert

03. 円周率¶

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

In [24]:
def is_a_to_z(char: str):
    return char >= 'a' and char <= 'z' or char >= 'A' and char <= 'Z'

def yield_words(s: str):
    w = ''
    for char in s:
        if is_a_to_z(char):
            w += char
        else:
            if w != '':
                yield w
                w = ''

string = 'Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.'
words = yield_words(string)

for w in words:
    print(w, len(w))
Now 3
I 1
need 4
a 1
drink 5
alcoholic 9
of 2
course 6
after 5
the 3
heavy 5
lectures 8
involving 9
quantum 7
mechanics 9

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

In [39]:
def is_a_to_z(char: str):
    return char >= 'a' and char <= 'z' or char >= 'A' and char <= 'Z'

def to_words(s: str):
    if s == '':
        return
    
    for i in range(0, len(s)):
        if not is_a_to_z(s[i]):
            yield from to_words(s[0:i])
            yield from to_words(s[i+1:])
            break
    else:
        yield s

words = list(to_words(
    "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
))

d = {}
for i in range(0, len(words)):
    w = words[i]
    if i in [1,5,6,7,8,9,15,16,19]:
        d.setdefault(w[0:1], w)
    else:
        d.setdefault(w[0:2], w)

from pprint import pprint
pprint(d)
{'Al': 'Also',
 'Ar': 'Arthur',
 'Be': 'Because',
 'Bo': 'Boron',
 'C': 'Could',
 'F': 'Fluorine',
 'H': 'He',
 'Hi': 'Hi',
 'Ki': 'King',
 'Li': 'Lied',
 'Mi': 'Might',
 'N': 'Not',
 'Na': 'Nations',
 'O': 'Oxidize',
 'Pe': 'Peace',
 'S': 'Security',
 'Si': 'Sign'}

05. n-gram¶

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

In [26]:
from typing import Sequence

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

s = "I am an NLPer"

print(f"文字tri-gram: {ngram(s, 3)}")
print(f'単語bi-gram:" {ngram(s.split(), 2)}')
文字tri-gram: ['I a', ' am', 'am ', 'm a', ' an', 'an ', 'n N', ' NL', 'NLP', 'LPe', 'Per']
単語bi-gram:" [['I', 'am'], ['am', 'an'], ['an', 'NLPer']]

06. 集合¶

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

In [41]:
def ngram(s: Sequence, n):
    return [ s[i:i+n] for i in range(0, len(s) - n + 1)]

x = set(ngram('paraparaparadise', 2))
y = set(ngram('paragraph', 2))

print(
    f"X: {x}",
    f"Y: {y}",
    f"X ⋃ Y: {x.union(y)}",
    f"X ⋂ Y: {x.intersection(y)}",
    f"X \\ Y {x.difference(y)}",
    f"X ⋃ Y: {x.union(y)}",
    '',
    f"'se' in X: {'se' in x}",
    f"'se' in Y: {'se' in y}",
    sep="\n",
)
X: {'pa', 'ra', 'ar', 'ad', 'is', 'di', 'se', 'ap'}
Y: {'pa', 'ra', 'ar', 'gr', 'ag', 'ap', 'ph'}
X ⋃ Y: {'pa', 'ra', 'ar', 'ad', 'is', 'di', 'se', 'gr', 'ag', 'ap', 'ph'}
X ⋂ Y: {'pa', 'ap', 'ar', 'ra'}
X \ Y {'ad', 'is', 'di', 'se'}
X ⋃ Y: {'pa', 'ra', 'ar', 'ad', 'is', 'di', 'se', 'gr', 'ag', 'ap', 'ph'}

'se' in X: True
'se' in Y: False

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

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

In [28]:
def genarate_sentence_by_template(x, y, z):
    return f"{x}時の{y}は{z}"

print(genarate_sentence_by_template(12, "気温", 22.4))
12時の気温は22.4

08. 暗号文¶

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

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

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

In [29]:
def cipher(s: str):
    res = ""
    for c in s:
        if 'a' <= c and c <= 'z':
            res += str(219 - ord(c))
        else:
            res += c
    return res

print(cipher("Hello, World!"))
H118111111108, W108105111119!

09. Typoglycemia¶

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

In [38]:
import random

def typoglycemia(s: str):
    words = s.split()
    res = []
    for w in words:
        if len(w) <= 4:
            res += w
            continue
        res.append(w[1] + ''.join(random.sample(w[1:-1], len(w)-2)) + w[-1])
    return res

print(typoglycemia("I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."))
['I', "on'udlot", 'eveilee', 't', 'h', 'a', 't', 'I', 'oolud', 'clactluy', 'nrntseadnd', 'w', 'h', 'a', 't', 'I', 'w', 'a', 's', 'eaindeg', ':', 't', 'h', 'e', 'hanoehenml', 'oeowr', 'o', 'f', 't', 'h', 'e', 'umaun', 'm', 'i', 'n', 'd', '.']