#!/usr/bin/env python3
"""
第 34 轮:十七不在方格里,方格里却全是十七。

34 的身份核查 + Dürer 幻方(1..16,魔数 34)的深层解剖:

  - 34 = 2×17:这一轮的编号是老朋友十七的两倍
  - 34 = F₉ = 13+21:斐波那契第九步,风铃的 13 拉着 21 的手
  - φ(34) = φ(2)×φ(17) = 1×16 = 16 —— 恰好是幻方的格子数(顶角那一格也是 16)
  - σ(34) = 1+2+17+34 = 54;d(34) = 4(因子 1,2,17,34 里又有 17)
  - 34 = 3²+5²;也是 16²+30² = 34² 的斜边——而 (16,30,34) = 2×(8,15,17),
    这条勾股弦是 (8,15,17) 翻倍来的:34 的斜边身份,依然盖在 17 的地基上
  - 34 的二进制 = 100010,回文里嵌着两个 17 的 1

Dürer 幻方的核心秘密(本轮实测):
  - 16 个格子,1..16,每行/列/对角线之和 = 34
  - 关于中心对称的两格(对径对)之和恒为 17:16+1、3+14、2+15、13+4、
    5+12、10+7、11+6、9+8 —— 八对十七
  - 于是每条经典线 = 两个对径对 = 17+17 = 34:十七不在方格里,方格里却全是它
  - 全部 C(16,4) = 1820 种四格取法里,有 N 种和为 34(N 实测,传闻是 86)
"""

from itertools import combinations
import math

DURER = [
    [16, 3, 2, 13],
    [5, 10, 11, 8],
    [9, 6, 7, 12],
    [4, 15, 14, 1],
]
N = len(DURER)  # 4
MAGIC = N * (N * N + 1) // 2  # 34


def cell(r, c):
    return DURER[r][c]


def antipode(r, c):
    """关于幻方中心对称的格子(对径格)"""
    return (N - 1 - r, N - 1 - c)


def main():
    print("== 34 的身份核查(第 34 轮 = 魔数 = 十七的两倍) ==")
    assert 34 == MAGIC
    print(f"34 = 4×(4²+1)/2 = 魔数:十六个格子 1..16,所有行/列/对角线都指向它")

    fib = [1, 1]
    while fib[-1] < 100:
        fib.append(fib[-1] + fib[-2])
    assert fib[8] == 34 and fib[6] == 13 and fib[7] == 21
    print(f"34 = F₉(斐波那契第九步)= F₇+F₈ = 13+21:风铃的 13,拉着 21 的手")

    # φ(34) = 34·(1−1/2)(1−1/17)
    phi34 = 34 * (1 - 1 / 2) * (1 - 1 / 17)
    assert phi34 == 16.0
    assert 34 == 2 * 17 and 34 == 3**2 + 5**2
    ds = [d for d in range(1, 35) if 34 % d == 0]
    assert ds == [1, 2, 17, 34]
    print(f"φ(34) = {int(phi34)} = 幻方的格子数(顶角那格也写着 16);d(34) = {len(ds)} = 因子 {ds} 里又有 17")
    assert 16**2 + 30**2 == 34**2 and (8, 15, 17) == (16 // 2, 30 // 2, 34 // 2)
    print(f"34 = 3²+5²;且 16²+30² = 34² —— 勾股弦 (16,30,34) = 2×(8,15,17),斜边身份也盖在 17 的地基上")
    assert bin(34) == "0b100010"
    print(f"34 的二进制 = {bin(34)[2:]}(回文,首尾两个 1 隔 4 位,像两个 17 隔空相望)")

    print("\n== Dürer 幻方(魔数 34) ==")
    for row in DURER:
        print("  " + "  ".join(f"{x:>2}" for x in row))

    lines = [row for row in DURER] + [[DURER[r][c] for r in range(N)] for c in range(N)]
    lines += [[DURER[i][i] for i in range(N)], [DURER[i][N - 1 - i] for i in range(N)]]
    assert all(sum(line) == MAGIC for line in lines)
    print(f"4 行 + 4 列 + 2 对角线共 {len(lines)} 条线,和全是 {MAGIC} ✅")

    print("\n== 对径对:八对十七 ==")
    pairs, seen = [], set()
    for r in range(N):
        for c in range(N):
            if (r, c) in seen:
                continue
            ar, ac = antipode(r, c)
            seen.add((r, c))
            seen.add((ar, ac))
            a, b = cell(r, c), cell(ar, ac)
            assert a + b == 17, f"对径对 ({a},{b}) 之和不等于 17!"
            pairs.append((a, b))
    print(f"关于中心对称的两格之和恒为 17,共 {len(pairs)} 对:"
          + "、".join(f"{a}+{b}" for a, b in pairs))

    # 每条经典线 = 两个对径对 = 17+17
    for name, line in (
        ("行1", DURER[0]), ("行2", DURER[1]), ("行3", DURER[2]), ("行4", DURER[3]),
        ("列1", [DURER[r][0] for r in range(N)]),
        ("列2", [DURER[r][1] for r in range(N)]),
        ("列3", [DURER[r][2] for r in range(N)]),
        ("列4", [DURER[r][3] for r in range(N)]),
        ("主对角", [DURER[i][i] for i in range(N)]),
        ("副对角", [DURER[i][N - 1 - i] for i in range(N)]),
    ):
        s = sum(line)
        assert s == 34
        print(f"  {name}: {'+'.join(map(str, line))} = {s} = 17+17")

    print("\n== 全部四格取法:和为 34 的有多少种? ==")
    cells = [(r, c) for r in range(N) for c in range(N)]
    total = 0
    good = []
    for quad in combinations(cells, 4):
        total += 1
        if sum(cell(r, c) for r, c in quad) == MAGIC:
            good.append(quad)
    straight = 0
    for quad in good:
        rs = {r for r, c in quad}
        cs = {c for r, c in quad}
        if len(rs) == 1 or len(cs) == 1 or quad == tuple((i, i) for i in range(N)) \
                or quad == tuple((i, N - 1 - i) for i in range(N)):
            straight += 1
    print(f"C(16,4) = {total} 种取法,和为 34 的共 {len(good)} 种")
    print(f"其中平直的四格线(行/列/对角线)只有 {straight} 条,其余 {len(good)-straight} 种都是拐弯的形状")
    assert len(good) == 86, f"四格取法实测 {len(good)} 种,不是传闻的 86!"
    assert straight == 10
    print(f"✅ 传闻属实:四格取法 86 种,每一种都是 34;直的只有 10 条,弯的有 76 种")

    print("\n== 结论 ==")
    print("十七不在方格里——十六个格子没有它;方格里却全是它:")
    print("八对十七铺成整张桌子,每一条线都是它碰杯两次。")
    print("而这一轮的编号 34,不过就是 17+17:老朋友等了 18 轮,终于轮到自己当魔数。")

    gen_svg(pairs)
    print("\n已生成 content/code/garden_magic34.svg")


def gen_svg(pairs):
    """画一张 Dürer 幻方:八对对径格八种颜色,每对之和都是 17。"""
    hues = ["#e74c3c", "#e67e22", "#f1c40f", "#2ecc71", "#1abc9c", "#3498db", "#9b59b6", "#e84393"]
    pair_color = {}
    for (a, b), hue in zip(pairs, hues):
        pair_color[a] = pair_color[b] = hue
    # 找出每个数字的格子坐标
    pos = {}
    for r in range(N):
        for c in range(N):
            pos[cell(r, c)] = (r, c)

    S, G, M = 90, 14, 60  # 格宽、间隙、边距
    W = M * 2 + G * (N - 1) + S * N
    H = M + 150 + M + S * N + M + 90
    x0 = y0 = M

    def rx(i):
        return x0 + i * (S + G)

    def ry(j):
        return y0 + j * (S + G)

    parts = [f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" '
             f'viewBox="0 0 {W} {H}" font-family="serif">']
    parts.append(f'<rect width="{W}" height="{H}" fill="#0e1420"/>')
    parts.append(f'<text x="{W/2:.0f}" y="{M+34}" text-anchor="middle" font-size="30" '
                 f'fill="#f5f0e1">十七不在方格里,方格里却全是十七</text>')
    parts.append(f'<text x="{W/2:.0f}" y="{M+62}" text-anchor="middle" font-size="17" '
                 f'fill="#8fa3bf">Dürer 幻方 · 魔数 34 = 2×17 = F₉ = 13+21 · 第 34 轮</text>')

    # 对径连线(画在格下层)
    for a, b in pairs:
        ar, ac = pos[a]
        br, bc = pos[b]
        xa, ya = rx(ac) + S / 2, ry(ar) + S / 2
        xb, yb = rx(bc) + S / 2, ry(br) + S / 2
        parts.append(f'<line x1="{xa:.0f}" y1="{ya:.0f}" x2="{xb:.0f}" y2="{yb:.0f}" '
                     f'stroke="{pair_color[a]}" stroke-width="2.5" stroke-dasharray="6 5" opacity="0.55"/>')

    # 格子
    for r in range(N):
        for c in range(N):
            v = cell(r, c)
            col = pair_color[v]
            parts.append(f'<rect x="{rx(c):.0f}" y="{ry(r):.0f}" width="{S}" height="{S}" rx="10" '
                         f'fill="{col}" opacity="0.16" stroke="{col}" stroke-width="2"/>')
            parts.append(f'<text x="{rx(c)+S/2:.0f}" y="{ry(r)+S/2+12:.0f}" text-anchor="middle" '
                         f'font-size="34" fill="#f5f0e1" font-weight="bold">{v}</text>')

    # 行注释:每行 = 34 = 17+17
    for r in range(N):
        s = sum(DURER[r])
        parts.append(f'<text x="{rx(N-1)+S+G+6:.0f}" y="{ry(r)+S/2+12:.0f}" font-size="19" '
                     f'fill="#f5f0e1">= {s} = 17+17</text>')
    # 列注释(底部)
    for c in range(N):
        s = sum(DURER[r][c] for r in range(N))
        parts.append(f'<text x="{rx(c)+S/2:.0f}" y="{ry(N-1)+S+38:.0f}" text-anchor="middle" '
                     f'font-size="17" fill="#8fa3bf">↓ {s}</text>')

    # 图例(两行,每行 4 对,保证不粘连)
    ly = ry(N - 1) + S + 66
    parts.append(f'<text x="{x0:.0f}" y="{ly:.0f}" font-size="16" fill="#8fa3bf">八对对径格,每对之和都是 17:</text>')
    for i, (a, b) in enumerate(pairs):
        col_i, row_i = i % 4, i // 4
        cx = x0 + (col_i + 0.5) * (W - 2 * x0) / 4
        cy = ly + 20 + row_i * 34
        parts.append(f'<circle cx="{cx:.0f}" cy="{cy:.0f}" r="6" fill="{hues[i]}"/>')
        parts.append(f'<text x="{cx:.0f}" y="{cy+20:.0f}" text-anchor="middle" font-size="13" '
                     f'fill="#c9d4e3">{a}+{b}=17</text>')

    parts.append(f'<text x="{W/2:.0f}" y="{H-22:.0f}" text-anchor="middle" font-size="14" '
                 f'fill="#5f7396">86 种四格取法,和为 34 的恰好 86 种 —— 每一种都是十七碰两次杯</text>')
    parts.append("</svg>")
    with open("garden_magic34.svg", "w", encoding="utf-8") as f:
        f.write("\n".join(parts))


if __name__ == "__main__":
    main()
    print("全部断言通过 ✅")
