AI와 수학교육

5편. 에셔는 ........

world1000 2026. 8. 5. 06:00

연재 「당신도 모르는 수학 이야기 ― 수학이란 무엇인가」 · 5편

1937년 10월, 헤이그.

마우리츠 에셔가 부모님 댁에 들릅니다. 형 베런트도 와 있었지요. 베런트는 라이덴 대학에서 돌과 광물을 연구하는 사람이었습니다.

에셔는 요즘 새긴 목판화를 형에게 꺼내 보입니다. 같은 무늬가 옆으로 계속 이어지는 그림이었어요. 형이 한참을 들여다보더니 이렇게 말합니다.

"이거, 내가 하는 일하고 닮았는데?"

형이 다루는 것은 결정체였습니다. 소금 알갱이나 눈송이 같은 것들이요. 그 속에서는 원자가 아무렇게나 흩어져 있지 않고 줄을 맞춰 늘어섭니다. 같은 배열이 옆으로 위로 끝없이 되풀이되지요. 형은 동생의 그림에서 그 되풀이 패턴을 알아본 겁니다.

얼마 뒤 형에게서 편지가 옵니다. 논문 열 편의 목록이었어요. 하크, 폴리아, 니글리, 라베스, 헤슈. 1911년부터 1933년 사이에 『Zeitschrift für Kristallographie』에 실린 글들이었습니다.

이것이 에셔가 수학과 처음 닿은 순간입니다. 그때 그는 서른아홉이었습니다.

화가에게 왜 논문이 필요했을까

15년 전으로 돌아가 보겠습니다.

1922년, 에셔는 그라나다의 알함브라 궁전에 들어섭니다. 벽과 천장이 온통 무늬였습니다. 그는 감탄했고 몇 장을 베껴 두고 떠났지요.

그런데 그 화려한 벽 어디에도 사람이 없었습니다. 동물도 없었고 꽃조차 거의 없었어요. 오로지 도형뿐이었습니다. 이슬람의 종교 미술은 형상을 그리지 않았고, 그래서 무어의 장인들은 기하 무늬만으로 벽을 채우는 길을 갔던 겁니다.

정팔각형과 정사각형이 빈틈없이 맞물리고, 팔각형 안에 여덟 갈래 별이 들어갑니다.

1936년에 에셔는 알함브라를 다시 찾아갑니다. 이번에는 며칠을 머물며 문양을 꼼꼼히 베꼈어요. 지금까지 얻은 것 중 가장 풍부한 영감의 원천이었다고 그는 나중에 말했습니다.

돌아온 에셔가 하고 싶었던 일은 분명했습니다. 알함브라의 그 무늬 자리에 새를 넣고, 물고기를 넣고, 도마뱀을 넣는 것이었지요.

그런데 방법을 몰랐습니다. 새들이 서로 물리게 하려면 무엇을 어떻게 해야 할까요?

새 한 마리를 그리는 것이야 어렵지 않습니다. 문제는 그 새들이 서로 물려 빈틈없이 이어져야 한다는 것이었어요. 한 마리의 등이 다른 마리의 배가 되고, 날개가 꼬리에 딱 맞물려야 합니다. 조금이라도 어긋나면 틈이 생깁니다.

그는 새와 사자와 역도 선수를 그려 보았습니다. 그런데 자기 상상과 스페인에서 베껴 온 밑그림에만 기대다 보니 한 장에 엄청난 시간이 들었네요.

그러던 참에 형이 목록을 보낸 것입니다.

폴리아가 헤아린 것

폴리아의 논문에 무엇이 적혀 있었는지 잠깐 보고 가겠습니다. 에셔가 읽지 못한 것이 이것이거든요.

정사각형 한 장을 종이에 그려 놓고 손으로 돌려 봅시다.

90도 돌리면 원래와 똑같아 보입니다. 180도도, 270도도, 360도도 그렇지요. 여기까지 네 가지입니다.

뒤집어도 됩니다. 세로로 반 접듯 뒤집으면 똑같고, 가로로 뒤집어도 똑같습니다. 대각선으로 뒤집는 것도 두 가지가 있고요. 네 가지입니다.

돌리기 넷에 뒤집기 넷, 모두 여덟 가지입니다.

이제 이런 걸 해 봅시다. 90도 돌린 다음에 세로로 뒤집습니다. 두 동작을 이어서 한 것이지요. 그 결과를 보면 대각선으로 뒤집은 것과 똑같습니다.

여덟 가지 중에 아무거나 둘을 골라 이어서 해 보세요. 나오는 결과는 언제나 여덟 가지 중 하나입니다. 아홉 번째가 생기는 일이 없어요.

이렇게 아홉 번째가 생기지 않는 모임을 군(group)이라고 합니다. 정사각형을 원래대로 두는 여덟 가지 움직임, 이것이 정사각형의 대칭군(symmetry group)입니다.

무늬로 옮겨 오면

같은 일을 평면의 무늬에도 해 볼 수 있습니다. 무늬를 원래대로 두는 움직임을 모두 모으는 것이지요.

그런데 여기서 한 가지를 가정하고 시작해야 합니다.

실제 벽지는 벽 크기만큼이고 문살은 문짝 크기입니다. 유한하지요. 그런데 유한한 무늬에서는 옆으로 옮기는 것이 대칭이 될 수 없습니다. 한 칸 옮기면 한쪽 끝이 밖으로 나가 버리니까요. 그래서 수학에서는 무늬가 평면 전체로 끝없이 이어진다고 가정합니다. 벽지 무늬를 벽이 아니라 평면 전체에 깔아 놓은 것으로 여기는 것이죠.

그렇게 두면 옮기기도 대칭이 됩니다. 문살에서 꽃 하나를 오른쪽으로 한 칸 옮기면 문짝 전체가 원래와 똑같아 보이잖아요.

여기서 재미있는 것이 나옵니다. 문짝을 원래대로 두는 옮기기는 무수히 많습니다. 오른쪽 세 칸도, 왼쪽 두 칸에 위로 한 칸도 그렇지요. 그런데 그 무수한 옮기기가 전부 두 가지에서 나옵니다. 오른쪽 한 칸과 위로 한 칸, 이 둘을 몇 번씩 되풀이하면 나머지가 다 만들어지거든요. 오른쪽 세 칸은 오른쪽 한 칸을 세 번 한 것이고, 왼쪽 두 칸에 위로 한 칸은 오른쪽 한 칸을 거꾸로 두 번 하고 위로 한 칸을 한 번 한 것입니다.

두 방향으로 반복된다는 말이 이것입니다.

이런 무늬의 대칭군을 벽지군(wallpaper group)이라 합니다. 그리고 폴리아가 헤아린 것이 바로 이 벽지군이 몇 가지인가였어요.

열일곱은 어떻게 세는가

세는 일은 두 단계로 나뉩니다.

첫 단계는 회전이 몇 차까지 가능한지 정하는 일입니다. 3편에서 우리가 증명한 그것이지요. 반복되는 평면 무늬가 가질 수 있는 회전은 2차, 3차, 4차, 6차뿐입니다. 결정학적 제한 정리(crystallographic restriction theorem)라 부르는데, 결정체 속 원자 배열도 반복되는 격자를 이루므로 같은 제한을 받기 때문에 결정학(crystallography)에서 나온 이름이 붙었습니다.

두 번째 단계는 각 회전 차수마다 뒤집기와 미끄러뜨리기를 어떻게 붙일 수 있는지 헤아리는 일입니다. 그 수를 더하면 4 + 5 + 3 + 3 + 2, 곧 열일곱이 됩니다.

같은 조각 하나를 옮기고 돌리고 뒤집어 만든 것입니다. 주황색은 뒤집힌 조각이에요. p1과 p2와 p3처럼 청록뿐인 것은 뒤집기를 쓰지 않는 무늬입니다.

그런데 그는 읽지 못했습니다

에셔가 받은 논문에는 지금 우리가 본 것이 훨씬 빽빽한 말로 적혀 있었습니다.

그는 그것을 이해하지 못했습니다.

에셔는 수학에 강했던 적이 없고 배운 적도 없다고 스스로 말했습니다. 논문의 문장을 그는 따라가지 못했어요.

대신 그가 한 일이 있습니다. 논문에 실린 도표 열일곱 장을 손으로 하나하나 베껴 자기 공책에 옮겨 적었습니다.

글은 못 읽고 그림만 가져온 것입니다. 그것으로 무엇을 할 수 있었을까요?

그가 익힌 방법

가장 단순한 것부터 보겠습니다.

정사각형에서 시작합니다. 왼쪽 변을 안으로 파냅니다. 그리고 파낸 그 모양 그대로 오른쪽 변에 붙입니다. 아래도 파내어 위에 붙이고요.

모양이 완전히 달라졌는데도 넓이는 그대로입니다. 파낸 만큼 붙였으니까요. 그리고 이 모양은 여전히 빈틈없이 깔립니다. 왼쪽에서 파인 자리에 오른쪽에서 튀어나온 부분이 정확히 들어가거든요.

여기에 눈 두 개만 찍으면 무언가 살아 있는 것처럼 보이기 시작하더군요.

직접 해 보시죠. 왼쪽 그림의 점을 끌면 오른쪽 변이 따라 나옵니다.

파고 붙이기 ― 정사각형에서 제 모양 만들기

에셔가 새와 물고기를 만든 방법입니다. 왼쪽 그림의 점을 끌어 보세요. 오른쪽에서 그 모양이 곧바로 깔립니다.

어떻게 붙일지 먼저 고릅니다. 붙이는 방법이 달라지면 파는 규칙도 달라집니다.
점을 끌어 파고 붙입니다
깔린 모습

붙이는 방법을 바꾸면 인상이 또 달라집니다. 그냥 옮겨 붙이면 모든 도형이 같은 방향을 보고, 180도 돌려 붙이면 둘씩 마주 봅니다.

만드신 것이 있으면 저장해 두시죠. 당신의 열여덟 번째 장입니다. 물론 열여덟 번째는 없습니다. 무엇을 만드셨든 그것은 앞의 열일곱 중 하나예요.

도표 열일곱 장

에셔가 폴리아의 논문에서 가져온 것은 도표 열일곱 장이 전부였습니다. 왜 열일곱인지, 군이 무엇인지는 끝내 그의 것이 되지 못했습니다.

우리는 앞에서 그 열일곱 장을 보았습니다. 에셔가 자기 공책에 손으로 옮겨 적은 것이 그것입니다. 화가가 논문을 펼쳐 놓고 글자는 건너뛰고 그림만 따라 그리는 장면이지요.

그런데 그는 그 열일곱 장으로 137장을 그렸습니다. 1936년에 「평면의 규칙적 분할」 연작을 시작해 1958년에 같은 제목의 책을 냈고, 그림은 1960년대 후반까지 이어져 137번에서 멈춥니다.

스물두 해 동안 137장. 한 장에 두 달쯤 걸린 셈입니다. 왜 137에서 멈췄는지는 아무도 모릅니다. 그냥 거기서 그만둔 것이지요.

이해하지 못한 것을 붙들고 스물두 해를 보낸 사람입니다.

저는 이 대목에서 자꾸 멈추게 됩니다. 그는 증명을 몰랐는데도 규칙을 정확히 썼습니다. 도표가 증명을 대신한 셈이지요.

그러면 쓰는 데에 증명이 꼭 필요한 걸까요? 필요 없다면 증명은 무엇을 위해 있는 걸까요?

이 물음은 다음 편들에서 다른 얼굴로 돌아옵니다. 기계가 수학 문제를 풀기 시작했거든요. 기계도 증명 없이 답을 내놓습니다. 그것을 우리는 어떻게 받아들여야 할까요?

다음 편에서 우리는 불편한 이야기를 마주해야 합니다. 기계가 수학 경시대회에서 금메달을 받았습니다.


부록 하나 ― 정말 열일곱인지 따져 보기

앞의 그림은 제가 그린 것입니다. 그러니 믿을 이유가 없지요. 확인해 보겠습니다. 여기부터는 건너뛰셔도 본문을 읽는 데 지장이 없습니다.

그림 대신 목록으로

무늬 하나하나는 조각을 어떻게 옮기고 돌리고 뒤집는지 적은 변환 목록으로 나타낼 수 있습니다. p4는 이렇게 네 줄입니다.

(x, y) (−x, −y) (−y, x) (y, −x)

첫 줄은 그대로 두는 것이고, 둘째 줄은 180도 돌리는 것, 셋째와 넷째가 90도와 270도입니다. p4m은 여기에 뒤집기 넷이 붙어 여덟 줄이고, p6m은 열두 줄이에요. 열일곱을 다 적으면 일흔여덟 줄입니다.

이어 붙여 보기

본문에서 정사각형으로 확인한 셋을 그대로 보면 됩니다. 둘을 이어 붙였을 때 목록 밖으로 나가지 않는지, 아무것도 안 하는 변환이 있는지, 되돌리는 변환이 있는지요.

p4g에서 3번과 5번을 이어 붙여 보겠습니다.

(−y, x) 다음에 (−x+1/2, y+1/2)
= (−y+1/2, −x+1/2)
목록의 8번입니다

밖으로 나가지 않았습니다. 그런데 손으로 다 하기는 벅찹니다. p6m 하나만 해도 12 × 12로 144가지이고, 열일곱을 다 하면 486가지니까요.

직접 눌러 보시죠.

정말 열일곱인지 따져 보기

벽지 무늬 열일곱 가지는 각각 변환 목록으로 적을 수 있습니다. 그 목록이 정말 군인지, 곧 둘을 이어 붙여도 목록 밖으로 나가지 않는지 직접 확인해 보세요.

1무늬를 하나 고릅니다
이 무늬를 만드는 변환 4가지입니다. 둘을 골라 눌러 보세요.
2둘을 이어 붙이면
위에서 변환 두 개를 눌러 보세요.
3전부 확인해 봅니다

손으로 다 하기는 벅찹니다. 변환이 여덟이면 8 × 8로 64가지, 열둘이면 144가지니까요.

단추를 눌러 보세요.

486가지 가운데 목록 밖으로 나간 것이 하나도 없습니다. 항등원과 역원도 열일곱 군데 모두 있고요.

겉이 같아 보이는 것들

그런데 이것만으로는 부족합니다. 열일곱이 서로 다르다는 것을 아직 못 보였거든요.

p3m1과 p31m을 보시죠. 둘 다 3차 회전이고, 둘 다 거울이 셋이며, 목록의 길이도 여섯으로 같습니다. 겉으로는 구별할 방법이 없어요.

갈라내려면 다른 것을 봐야 합니다. 무늬의 한 칸 안에 3차 회전 중심이 셋 있는데, 그 셋이 거울 위에 있는지를 세면 이렇게 갈립니다.

p3m1 — 세 중심이 모두 거울 위에 (3/3)
p31m — 하나만 거울 위에 (1/3)

p4m과 p4g도 같습니다. 한 칸 안에 4차 회전 중심이 둘인데, p4m은 둘 다 거울 위에 있고 p4g는 하나도 없습니다.

저는 이 대목이 오래 걸립니다. 겉모습이 같아 보여도 다른 것일 수 있습니다. 눈으로 세면 안 되고 성질로 갈라야 하지요. 3편에서 깔아 보는 것과 증명하는 것이 다르다고 했던 이야기가 여기서 다시 나옵니다.


부록 둘 ― 직접 돌려 보기

위의 검산을 파이썬으로 옮기면 이렇습니다. 쉰 줄 남짓입니다.

import numpy as np

GROUPS = {
    "p1":   ["x,y"],
    "p2":   ["x,y", "-x,-y"],
    "pm":   ["x,y", "-x,y"],
    "pg":   ["x,y", "-x,y+1/2"],
    "cm":   ["x,y", "-x,y"],
    "pmm":  ["x,y", "-x,y", "x,-y", "-x,-y"],
    "pmg":  ["x,y", "-x,-y", "-x+1/2,y", "x+1/2,-y"],
    "pgg":  ["x,y", "-x,-y", "-x+1/2,y+1/2", "x+1/2,-y+1/2"],
    "cmm":  ["x,y", "-x,-y", "-x,y", "x,-y"],
    "p4":   ["x,y", "-x,-y", "-y,x", "y,-x"],
    "p4m":  ["x,y", "-x,-y", "-y,x", "y,-x",
             "-x,y", "x,-y", "y,x", "-y,-x"],
    "p4g":  ["x,y", "-x,-y", "-y,x", "y,-x",
             "-x+1/2,y+1/2", "x+1/2,-y+1/2", "y+1/2,x+1/2", "-y+1/2,-x+1/2"],
    "p3":   ["x,y", "-y,x-y", "-x+y,-x"],
    "p3m1": ["x,y", "-y,x-y", "-x+y,-x", "-y,-x", "-x+y,y", "x,x-y"],
    "p31m": ["x,y", "-y,x-y", "-x+y,-x", "y,x", "x-y,-y", "-x,-x+y"],
    "p6":   ["x,y", "-y,x-y", "-x+y,-x", "-x,-y", "y,-x+y", "x-y,x"],
    "p6m":  ["x,y", "-y,x-y", "-x+y,-x", "-x,-y", "y,-x+y", "x-y,x",
             "-y,-x", "-x+y,y", "x,x-y", "y,x", "x-y,-y", "-x,-x+y"],
}
CENTERED = {"cm", "cmm"}


def parse(text):
    """'-x+y,y' 를 2×2 행렬과 평행이동 벡터로 옮긴다"""
    M, v = np.zeros((2, 2)), np.zeros(2)
    for i, part in enumerate(text.split(",")):
        for term in part.replace("-", "+-").split("+"):
            if not term:
                continue
            sign = -1 if term.startswith("-") else 1
            body = term.lstrip("-")
            if "/" in body:
                a, b = body.split("/")
                v[i] += sign * int(a) / int(b)
            elif body == "x":
                M[i, 0] += sign
            elif body == "y":
                M[i, 1] += sign
    return M, v


def compose(f, g):
    """f 다음에 g 를 한 것"""
    (M1, v1), (M2, v2) = f, g
    return M1 @ M2, M1 @ v2 + v1


def label(f, centered):
    """격자만큼 옮긴 것은 같은 변환으로 본다"""
    M, v = f
    unit = 2 if centered else 1
    w = (v * unit) % 1 / unit
    return tuple(np.round(M.ravel()).astype(int)), tuple(np.round(w, 6))


def check(name):
    centered = name in CENTERED
    elems = [parse(t) for t in GROUPS[name]]
    table = {label(e, centered) for e in elems}
    ident = label((np.eye(2), np.zeros(2)), centered)

    closed = all(label(compose(a, b), centered) in table
                 for a in elems for b in elems)
    has_id = ident in table
    has_inv = all(any(label(compose(a, b), centered) == ident for b in elems)
                  for a in elems)
    return closed, has_id, has_inv, len(elems)


total = pairs = 0
for name in GROUPS:
    closed, has_id, has_inv, n = check(name)
    total += n
    pairs += n * n
    print(name, n, closed, has_id, has_inv)
print("변환", total, "개 · 조합", pairs, "가지")

돌려 보면 열일곱 줄이 모두 참으로 나오고, 마지막에 변환 78개와 조합 486가지가 찍힙니다.

여기서 눈여겨볼 것은 label 함수입니다. 격자만큼 옮긴 것을 같은 변환으로 보는 대목인데, 이것이 없으면 무늬가 무한하다는 가정이 코드에 반영되지 않습니다. 본문에서 말한 그 가정이 여기 한 줄로 들어가 있어요.


부록 셋 ― 파고 붙인 도형이 정말 깔릴까

에셔는 도형을 만들어 놓고 그려 봐야 알았습니다. 빈틈이 생기는지 아닌지를요. 그런데 그리기 전에 확인하는 방법이 있습니다.

둘만 보면 됩니다. 넓이가 1인지, 그리고 이웃과 맞닿는 변이 서로 일치하는지요.

넓이가 1이어야 하는 까닭은 이렇습니다. 한 칸에 도형 하나가 빈틈없이 들어가려면 도형이 칸을 정확히 메워야 합니다. 파낸 만큼 붙였다면 넓이가 그대로 1일 테고, 어긋났다면 1이 아니겠지요.

변이 일치해야 하는 까닭도 분명합니다. 내 오른변과 오른쪽 이웃의 왼변은 같은 선이어야 합니다. 다르면 그 사이에 틈이나 겹침이 생깁니다.

코드로 옮기면 이렇습니다.

import numpy as np

CORNER = [np.array([0., 0.]), np.array([1., 0.]),
          np.array([1., 1.]), np.array([0., 1.])]
CENTER = np.array([0.5, 0.5])


def rot(k):
    """90도씩 k번 돌리는 행렬"""
    c, s = round(np.cos(np.pi / 2 * k)), round(np.sin(np.pi / 2 * k))
    return np.array([[c, -s], [s, c]], float)


def curve(i, ctrl):
    """변 i(꼭짓점 i에서 i+1로) 위에 조절점을 얹은 곡선"""
    a, b = CORNER[i], CORNER[(i + 1) % 4]
    u = b - a
    n = np.array([-u[1], u[0]])          # 왼쪽 법선
    return [a] + [a + t * u + d * n for t, d in ctrl] + [b]


def make(mode, ctrl):
    """네 변을 만든다. ctrl 은 아래변에 얹을 (위치, 깊이) 목록"""
    if mode == "옮겨 붙이기":
        e0 = curve(0, ctrl)                                   # 아래
        e2 = [p + np.array([0., 1.]) for p in e0][::-1]       # 위 = 아래를 올린 것
        e3 = curve(3, ctrl)                                   # 왼쪽
        e1 = [p + np.array([1., 0.]) for p in e3][::-1]       # 오른쪽 = 왼쪽을 옮긴 것
        return [e0, e1, e2, e3]

    if mode == "180도 돌려 붙이기":
        # 각 변이 자기 가운데에 대해 점대칭
        sym = [(t, d) for t, d in ctrl] + [(1 - t, -d) for t, d in reversed(ctrl)]
        return [curve(i, sym) for i in range(4)]

    if mode == "90도 돌려 붙이기":
        # 아래변을 중심 둘레로 90도씩 돌려 나머지 세 변을 만든다
        e0 = curve(0, ctrl)
        return [[CENTER + rot(k) @ (p - CENTER) for p in e0] for k in range(4)]

    raise ValueError(mode)


def outline(edges):
    """네 변을 이어 붙인 닫힌 곡선"""
    return [p for e in edges for p in e[:-1]]


def area(pts):
    n = len(pts)
    return abs(sum(pts[i][0] * pts[(i + 1) % n][1] - pts[(i + 1) % n][0] * pts[i][1]
                   for i in range(n))) / 2


def same(a, b):
    """두 곡선이 같은 점들로 이루어졌는가"""
    key = lambda s: sorted(tuple(np.round(p, 9)) for p in s)
    return key(a) == key(b)


def check(mode, ctrl):
    e0, e1, e2, e3 = make(mode, ctrl)
    pts = outline([e0, e1, e2, e3])

    # 오른쪽 이웃의 왼변, 위쪽 이웃의 아랫변을 만든다
    if mode == "180도 돌려 붙이기":
        flip = lambda p, cx, cy: np.array([2 * cx - p[0], 2 * cy - p[1]])
        right = [flip(p, 1.5, 0.5) for p in [q + np.array([1., 0.]) for q in e1]]
        upper = [flip(p, 0.5, 1.5) for p in [q + np.array([0., 1.]) for q in e2]]
    else:
        right = [p + np.array([1., 0.]) for p in e3]
        upper = [p + np.array([0., 1.]) for p in e0]

    return area(pts), same(e1, right), same(e2, upper)


if __name__ == "__main__":
    ctrl = [(0.25, 0.14), (0.50, -0.18), (0.75, 0.10)]
    print(f"{'만드는 방법':<18} {'넓이':>8}  오른쪽  위쪽   판정")
    for mode in ("옮겨 붙이기", "180도 돌려 붙이기", "90도 돌려 붙이기"):
        a, r, u = check(mode, ctrl)
        ok = abs(a - 1) < 1e-9 and r and u
        mark = lambda b: "○" if b else "✗"
        print(f"{mode:<18} {a:>8.4f}   {mark(r)}     {mark(u)}    "
              f"{'깔린다' if ok else '깔리지 않는다'}")

돌려 보면 이렇게 나옵니다.

만드는 방법                   넓이  오른쪽  위쪽   판정
옮겨 붙이기               1.0000   ○     ○    깔린다
180도 돌려 붙이기          1.0000   ○     ○    깔린다
90도 돌려 붙이기           0.9400   ✗     ✗    깔리지 않는다

90도가 걸립니다. 저는 세 번째 방식도 만들려고 했습니다. 아래변을 중심 둘레로 90도씩 돌려 나머지 세 변을 만드는 것이었지요. 그런데 넓이가 0.94로 나왔습니다.

까닭을 짚어 보면 이렇습니다. 90도로 돌리면 네 변이 모두 같은 모양이 됩니다. 한 변이 바깥으로 부풀면 네 변이 다 부풀고, 안으로 패이면 다 패이지요. 서로 상쇄되지 않으니 넓이가 1에서 벗어납니다. 옮겨 붙이기에서는 왼쪽에서 판 만큼 오른쪽에 붙으니 상쇄되고, 180도에서는 한 변 안에서 상쇄됩니다.

그래서 위젯에는 두 방식만 넣었습니다. 90도로 깔리는 무늬가 없다는 뜻은 아니에요. 앞의 열일곱 목록에 p4와 p4m과 p4g가 버젓이 있으니까요. 다만 파고 붙이기라는 이 방법으로는 만들 수 없다는 것입니다. 90도로 도는 무늬를 만들려면 도형 하나가 칸 하나를 통째로 차지하는 방식을 버려야 합니다.

에셔가 확인할 수 없었던 것이 이것입니다. 그는 그려 봐야 알았습니다. 우리는 넓이를 재고 변을 맞춰 보면 그리기 전에 압니다.


부록 넷 ― 군과 대칭군

본문에서는 정사각형으로 풀었습니다. 여기서는 수학에서 쓰는 방식대로 적어 두겠습니다. 건너뛰셔도 됩니다. 아래는 격식체로 씁니다.

집합 G와 그 위의 이항연산 · 이 주어졌다고 하자. 다음 셋이 성립하면 (G, ·)를 군이라 한다.

결합법칙 모든 a, b, c에 대해 (a · b) · c = a · (b · c)

항등원 모든 a에 대해 e · a = a · e = a 인 e가 있다

역원 각 a에 대해 a · b = b · a = e 인 b가 있다

연산의 결과가 다시 G 안에 있다는 것은 연산의 정의에 이미 들어 있다. 본문에서 아홉 번째가 생기지 않는다고 한 것이 이 대목이다.

정수 전체와 덧셈이 군이다. 결합법칙이 성립하고, 항등원은 0이며, a의 역원은 −a다.

H가 G의 부분집합이면서 같은 연산으로 다시 군이 되면 H를 G의 부분군이라 한다.

대칭군이라는 말의 두 가지 쓰임

집합 X에서 X로 가는 전단사 함수 전체는 합성에 대해 군을 이룬다. 합성은 언제나 결합적이고, 항등함수가 항등원이며, 전단사이므로 역함수가 있다. 이 군을 X의 대칭군이라 하고 Sym(X)로 쓴다. X의 원소가 n개이면 n차 대칭군 Sₙ이라 하며 크기는 n!이다.

한편 어떤 도형이나 무늬가 주어졌을 때, 그것을 그 자신으로 옮기는 변환만 모으면 Sym(X)의 부분군이 된다. 이것도 대칭군이라 부른다. 정사각형이면 여덟 개짜리 D₄이고, 네 꼭짓점의 자리바꿈 전체인 S₄가 24개이니 D₄는 그 부분군이다.

우리말이 두 뜻을 다 대칭군으로 옮기는 것이 혼란의 원인이다. 영어는 앞의 것을 symmetric group, 뒤의 것을 symmetry group이라 하여 갈라 쓴다. 폴리아가 다룬 것은 뒤의 것이다.

격자와 계수

무늬 F의 대칭군을 Γ(F)라 하고, 그중 평행이동만 모은 것을 T라 하자. T는 Γ(F)의 부분군이다.

T의 원소를 모두 만들어 내는 데 필요한 최소 개수를 T의 계수(rank)라 한다. 계수가 2이면 두 벡터 a와 b가 있어 T의 모든 원소가 ma + nb 꼴로 적힌다. 이때 T가 이루는 점의 모임을 격자(lattice)라 한다.

계수가 0이면 반복이 없는 무늬이고, 대칭군은 돌리기와 뒤집기만 남는다. 계수가 1이면 한 방향으로만 반복되는 띠 무늬이며 이런 것은 일곱 가지다. 계수가 2인 것, 곧 두 방향으로 반복되는 무늬의 대칭군을 벽지군이라 한다.

열일곱

벽지군을 헤아리는 일은 두 단계다.

첫 단계에서 회전 차수가 1, 2, 3, 4, 6으로 제한된다. 이것이 결정학적 제한 정리이며 3편에서 증명했다. 두 번째 단계에서 각 차수에 반사와 미끄럼반사를 결합하는 방법을 센다.

회전 벽지군 개수
없음 p1, pm, pg, cm 4
2차 p2, pmm, pmg, pgg, cmm 5
3차 p3, p3m1, p31m 3
4차 p4, p4m, p4g 3
6차 p6, p6m 2
합계 17

페도로프가 1891년에 이것을 증명했고, 폴리아가 1924년에 따로 다시 발견했다. 에셔의 책상에 놓인 것이 폴리아의 논문이다.


참고한 것

G. Pólya, Über die Analogie der Kristallsymmetrie in der Ebene, Zeitschrift für Kristallographie 60 (1924), 278–282.

E. S. Fedorov, Симметрия на плоскости, Записки Императорского С.-Петербургского Минералогического Общества 28 (1891), 345–390.

반응형