略解と解説
第1章
発展課題
六芒星の描画。
= Image.new("L", (256, 256), 255)
img = ImageDraw.Draw(img)
draw = 128
cx = 128
cy = 96
r - r, cy - r, cx + r, cy + r))
draw.ellipse((cx = 3
N = 2 * pi / N
s for i in range(N):
= s*i - 0.5 * pi
s1 = s1 + s * k
s2 = r * cos(s1) + cx
x1 = r * sin(s1) + cy
y1 = r * cos(s2) + cx
x2 = r * sin(s2) + cy
y2
draw.line((x1, y1, x2, y2))= s*(i+0.5) - 0.5 * pi
s1 = s1 + s * k
s2 = r * cos(s1) + cx
x1 = r * sin(s1) + cy
y1 = r * cos(s2) + cx
x2 = r * sin(s2) + cy
y2 draw.line((x1, y1, x2, y2))
第2章
課題2
def plot(draw, s):
= s // 2
hs = (255, 0, 0)
red = (0, 255, 0)
green = (0, 0, 255)
blue for x in range(s):
for y in range(s):
= complex(x - hs + 0.5, -y + hs + 0.5) / s * 4
z = newton(z)
z # ここを埋めよ
if z.real > 0.0:
= red
c else:
if z.imag > 0.0:
= green
c else:
= blue
c + 1, y + 1], fill=c) draw.rectangle([x, y, x
発展課題
def newton(x):
for _ in range(10):
= x - (x**4 - 1) / (4 * x**3)
x return x
def plot(draw, s):
= s // 2
hs = (255, 0, 0)
red = (0, 255, 0)
green = (0, 0, 255)
blue = (255, 0 ,255)
purple for x in range(s):
for y in range(s):
= complex(x - hs + 0.5, -y + hs + 0.5) / s * 4
z = newton(z)
z # ここを埋めよ
if z.real + z.imag > 0.0:
if z.real - z.imag > 0.0:
= red
c else:
= purple
c else:
if z.real - z.imag > 0.0:
= green
c else:
= blue
c + 1, y + 1], fill=c) draw.rectangle([x, y, x
第3章
課題2
def collatz(i):
print(i)
while (i!=1):
if (i%2==0):
= i // 2
i else:
= i * 3 + 1
i print(i)
発展課題
def collatz_graph(i, edges):
while (i!=1 and i!=3):
= i
j if (i%2==0):
= i // 2
i else:
= i * 3 + 3
i edges.add((j, i))
第7章
課題1-1
def kaidan(n):
# 終端条件
if n==1:
return 1
if n==2:
return 2
# 再帰部分
return kaidan(n-1)+kaidan(n-2)
課題2-1
def solve(x, y, step, maze):
if maze[x][y] == '*':
return
if isinstance(maze[x][y], int):
return
= step
maze[x][y] +1, y, step+1, maze) # 右を探索
solve(x# 残りを埋めよ
-1, y, step+1, maze)
solve(x+1, step+1, maze)
solve(x, y-1, step+1, maze) solve(x, y
第9章
そのまま実行すると、以下のように画像のところどころに黒い点が現れる「黒飛び」が発生する。
近似画像の「黒飛び」が発生するのは、画像のピクセルの値が0から255の範囲から超えてしまうためだ。関数svd
において、近似値を構成しているところで、以下のように最小値と最大値を指定してやると「黒飛び」がなくなる。
= np.asarray(ur * sr * vr)
b = np.clip(b, 0,255) # 最小値と最大値を指定 b
講義では「なぜ黒飛びが発生するか」を考察させると良い。
第10章
課題2-2
電卓に乗除算を追加する。
def calc(code):
= code.split()
data = []
stack for x in data:
print(stack, x, end=" => ")
if x == '+':
= stack.pop()
b = stack.pop()
a +b)
stack.append(aelif x == '-':
= stack.pop()
b = stack.pop()
a -b)
stack.append(a# 以下を追加
elif x == '*':
= stack.pop()
b = stack.pop()
a *b)
stack.append(aelif x == '/':
= stack.pop()
b = stack.pop()
a //b)
stack.append(aelse:
int(x))
stack.append(print(stack)
print(stack.pop())
発展課題
例えば「1 + 2 * 3 - 4」の例であれば、まず以下を実行する。
"a + b * c - d") dis.dis(
すると、以下のような結果が得られる。
1 0 LOAD_NAME 0 (a)
2 LOAD_NAME 1 (b)
4 LOAD_NAME 2 (c)
6 BINARY_MULTIPLY
8 BINARY_ADD
10 LOAD_NAME 3 (d)
12 BINARY_SUBTRACT 14 RETURN_VALUE
これを見ながら、逆ポーランド記法を組み立てる。LOAD_NAME
はそのまま値を、BINARY_MULITPLY
は乗算記号*
をと書いていくと1 2 3 * + 4 -
という文字列を作ることができる。「電卓」に入力してみると
"1 2 3 * + 4 -") calc(
[] 1 => [1]
[1] 2 => [1, 2]
[1, 2] 3 => [1, 2, 3]
[1, 2, 3] * => [1, 6]
[1, 6] + => [7]
[7] 4 => [7, 4]
[7, 4] - => [3] 3
と、正しい答え3が得られる。「(1 + 2 * 3) / 4」の場合も同様。
第12章
課題1
最初に選んだ箱が正解だった場合は、残りの箱からランダムに選ぶので、
= choice(rest_boxes) # ここを埋めよ(1) second_choice
また、最初に選んだ箱が正解ではなかった場合は、次に選ぶ箱は必ず正解になるので
= answer # ここを埋めよ(2) second_choice
課題2
左から右に通行可能な確率は、道路の通行可能確率pが0.5より小さいとほとんどゼロ、0.5より大きいとほぼ1という、ステップ関数のような関数になる。このように、パラメタを変えた時、あるところで系の状態が劇的に変化する現象を相転移と呼ぶ。パーコレーションは相転移を起こす最も簡単なモデルの一つである。
発展課題
def gacha(n):
= 0
cd = []
posters while len(set(posters)) < n:
1, n))
posters.append(random.randint(+= 1
cd return cd
第13章
課題2
@jit
def laplacian(m, n, s):
= 0.0
ts += s[m+1][n]
ts += s[m-1][n]
ts += s[m][n+1]
ts += s[m][n-1]
ts # ここを埋めよ
-= 4*s[m][n]
ts return ts