computation_model / knowledge

LaTeX로 적은 전이 함수 표를 코드로 옮기기

paul 2025.07.20 340words (1m)

튜링 머신의 전이 함수를 설계할 때는 손으로 적는 게 편하다. 상태 이름에 첨자가 붙고 화살표가 들어가니 LaTeX로 쓰게 된다.

text
$\delta (q_{checkeven}, 0) \rightarrow (q_{gotostart}, 0, L)$
$\delta (q_{checkeven}, 1) \rightarrow (q_{odd_{1t}}, 0, L)$
$\delta (q_{gotostart}, 0) \rightarrow (q_{gotostart}, 0, L)$

문제는 이걸 그대로 실행할 수 없다는 것이다. 서른 줄쯤 되는 표를 손으로 다시 치면 오타가 난다.

정규식 하나로

python
import re

p = re.compile(r'(q_[^,]+),\s*([01M])\)\s*\\rightarrow\s*\((q_[^,]+),\s*([01M]),\s*([RL])')

with open('deltas.txt', 'r') as f:
    for line in f:
        text = re.sub(r'[{}]', '', line.strip())
        res = p.search(text)

        cur = res.group(1)
        read = res.group(2)
        next = res.group(3)
        write = res.group(4)
        dir = res.group(5)

        dict[(cur, read)] = (next, write, dir)

중괄호를 먼저 다 지운다. q_{odd_{1t}}q_odd_1t 가 되는데, 첨자 구조가 그대로 이름의 밑줄로 바뀌어서 파이썬에서 쓸 수 있는 형태가 된다. 이 한 줄 덕분에 정규식이 중첩 괄호를 다룰 필요가 없어진다.

그 다음 다섯 조각을 뽑는다. 현재 상태, 읽은 기호, 다음 상태, 쓸 기호, 이동 방향이다.

[01M] 로 기호를 한정한 게 좋았다. 오타로 다른 글자가 들어가 있으면 searchNone 을 돌려주고 다음 줄에서 바로 멈춘다. 조용히 잘못된 표가 만들어지는 것보다 낫다.

출력을 그대로 붙여넣기

python
for i in dict:
    print(f'{i}: {dict[i]},')

dict를 만들어놓고 쓰는 게 아니라 소스 코드 형태로 찍는다.

text
('q_checkeven', '0'): ('q_gotostart', '0', 'L'),
('q_checkeven', '1'): ('q_odd_1t', '0', 'L'),

이걸 복사해서 시뮬레이터 파일의 deltas = { ... } 안에 붙여넣는다. 실행할 때마다 파일을 읽고 파싱하지 않아도 되고, 시뮬레이터는 파일 의존성이 없어진다.

실제로 시뮬레이터 쪽 코드에는 이 출력이 그대로 들어가 있다.

설계는 LaTeX로 하고, 변환은 한 번 돌리고, 결과는 소스에 박아둔다. 변환기를 파이프라인에 넣지 않고 코드 생성기로 쓴 셈이다. 표를 고칠 일이 자주 없다면 이 편이 단순하다.

남은 것

dict 를 변수 이름으로 썼다. 내장 이름을 가리는 것이라 같은 스코프에서 dict() 를 쓸 수 없게 된다. 짧은 스크립트라 문제가 되지 않았다.

파일 경로도 절대 경로로 박혀 있다. 한 번 쓰고 마는 도구라 그렇게 둔 것으로 보인다.