"""
皮薩諾週期 60 圓圈圖
Fibonacci mod 10 的週期為 60,將 60 個個位數排列於圓周上。
需要:matplotlib(pip install matplotlib)
"""
import math
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# ── 1. 產生皮薩諾數列(Fibonacci mod 10,週期 = 60)──────────────────────────
def pisano60():
seq = [0, 1]
for i in range(2, 60):
seq.append((seq[-1] + seq[-2]) % 10)
return seq
seq = pisano60()
N = 60
# ── 2. 角度工具(從正上方 -π/2 開始,順時針)───────────────────────────────
def angle(i):
return (i / N) * 2 * math.pi - math.pi / 2
def xy(r, i):
a = angle(i)
return math.cos(a) * r, math.sin(a) * r
# ── 3. 半徑設定 ───────────────────────────────────────────────────────────────
R_outer = 1.00 # 外圓
R_dot = 0.88 # 點的位置
R_label = 0.97 # 數字標籤
R_inner = 0.76 # 弦線端點 / 虛線圓
R_idx = 0.68 # 位置索引
# ── 4. 畫布 ───────────────────────────────────────────────────────────────────
fig, ax = plt.subplots(figsize=(8, 8), facecolor='#f5f2eb')
ax.set_aspect('equal')
ax.axis('off')
ax.set_xlim(-1.15, 1.15)
ax.set_ylim(-1.15, 1.15)
COLOR = '#1a1a1a'
# ── 5. 外圓與虛線內圓 ─────────────────────────────────────────────────────────
for r, lw, ls in [(R_outer, 0.8, '-'), (R_inner, 0.4, (0, (4, 4)))]:
circle = plt.Circle((0, 0), r, color=COLOR, fill=False,
linewidth=lw, linestyle=ls)
ax.add_patch(circle)
# 圓心點
ax.plot(0, 0, 'o', color=COLOR, markersize=3)
# ── 6. 刻度線 ─────────────────────────────────────────────────────────────────
for i in range(N):
major = (i % 5 == 0)
r_in = R_inner - 0.01 if major else R_inner + 0.03
r_out = R_outer + 0.04
x1, y1 = xy(r_in, i)
x2, y2 = xy(r_out, i)
ax.plot([x1, x2], [y1, y2],
color=COLOR,
linewidth=1.2 if major else 0.4,
alpha=0.6 if major else 0.25)
# ── 7. 弦線(i → (i + seq[i]) % 60)─────────────────────────────────────────
for i in range(N):
d = seq[i]
if d == 0:
continue # 跳過自環
j = (i + d) % N
x1, y1 = xy(R_inner, i)
x2, y2 = xy(R_inner, j)
ax.plot([x1, x2], [y1, y2],
color=COLOR, linewidth=0.35, alpha=0.12)
# ── 8. 點與數字標籤 ───────────────────────────────────────────────────────────
for i in range(N):
d = seq[i]
xd, yd = xy(R_dot, i)
xl, yl = xy(R_label, i)
# 點
size = 5 if d == 0 else 3
alpha = 1.0 if d == 0 else 0.65
ax.plot(xd, yd, 'o', color=COLOR, markersize=size, alpha=alpha)
# 數字(個位數)
ax.text(xl, yl, str(d),
ha='center', va='center',
fontsize=7.5,
fontweight='bold' if d == 0 else 'normal',
color=COLOR,
alpha=1.0 if d == 0 else 0.85)
# ── 9. 位置索引(每 5 格,內圈小字)──────────────────────────────────────────
for i in range(0, N, 5):
xi, yi = xy(R_idx, i)
ax.text(xi, yi, str(i),
ha='center', va='center',
fontsize=5.5, color=COLOR, alpha=0.35)
# ── 10. 標題 ──────────────────────────────────────────────────────────────────
ax.set_title('皮薩諾週期 — 60', fontsize=11,
color=COLOR, fontfamily='serif',
letter_spacing=3 if hasattr(ax.title, 'set_letterspacing') else None,
pad=12)
plt.tight_layout()
plt.savefig('pisano60.png', dpi=180, bbox_inches='tight',
facecolor=fig.get_facecolor())
plt.show()
print("已儲存 pisano60.png")






沒有留言:
張貼留言