합성곱 연습 문서의 문제 7 풀이 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""합성곱 연습 p6·p7: 2차원 합성곱.

p6: f = h = 단위 정사각형(0~1 × 0~1에서 1)이면 g(x, y) = tri(x) tri(y).
    네 구역 (1) xy (2) x(2 - y) (3) (2 - x)y (4) (2 - x)(2 - y). 꼭대기 g(1, 1) = 1.
p7: f는 m, n ∈ {-1, 0, 1}에서 1, h는 (m, n) = (1, 0), (0, -1), (0, 0)에서 1.
    g(m, n) = Σ f(k, l) h(m - k, n - l). 위에서부터(m = 2, 1, 0, -1), n = -2 … 1:
      m = 2:  0 1 1 1
      m = 1:  1 3 3 2
      m = 0:  1 3 3 2
      m = -1: 1 2 2 1
"""


def main() -> None:
    N = 300
    def g_num(x, y):
        s = 0
        for i in range(N):
            a = (i + 0.5) / N
            for j in range(N):
                b = (j + 0.5) / N
                if 0 <= x - a <= 1 and 0 <= y - b <= 1:
                    s += 1
        return s / N ** 2
    tri = lambda t: t if t <= 1 else 2 - t
    cases = [((0.4, 0.7), 0.4 * 0.7), ((0.5, 1.6), 0.5 * (2 - 1.6)),
             ((1.5, 0.3), (2 - 1.5) * 0.3), ((1.2, 1.8), (2 - 1.2) * (2 - 1.8)), ((1.0, 1.0), 1.0)]
    for (x, y), want in cases:
        assert abs(g_num(x, y) - want) < 0.01 and abs(tri(x) * tri(y) - want) < 1e-12
    f = {(m, n): 1 for m in (-1, 0, 1) for n in (-1, 0, 1)}
    h = {(1, 0): 1, (0, -1): 1, (0, 0): 1}
    g = {}
    for (k, l), a in f.items():
        for (p, q), b in h.items():
            g[(k + p, l + q)] = g.get((k + p, l + q), 0) + a * b
    table = [[g.get((m, n), 0) for n in (-2, -1, 0, 1)] for m in (2, 1, 0, -1)]
    assert table == [[0, 1, 1, 1], [1, 3, 3, 2], [1, 3, 3, 2], [1, 2, 2, 1]]
    assert g[(-1, -2)] == 1 and g[(2, 1)] == 1
    h4 = dict(h)
    h4[(0, 1)] = 1                                     # 변형 2: 점 하나 더하면 값 4인 칸
    g4 = {}
    for (k, l), a in f.items():
        for (p, q), b in h4.items():
            g4[(k + p, l + q)] = g4.get((k + p, l + q), 0) + a * b
    assert g4[(1, 0)] == 4 and g4[(0, 0)] == 4 and max(g4.values()) == 4
    print("ALL CHECKS PASSED")


if __name__ == "__main__":
    main()