Posts for: #Golang

Go 로 읽는 SICP Part 10: Go 로 Scheme 인터프리터 만들기 — 파서라는 청구서

SICP 4장은 Scheme 으로 Scheme 인터프리터를 씁니다. eval 과 apply 가 서로를 부르는 30줄 남짓으로 언어 하나가 정의됩니다. Go 로 옮기면 렉서와 파서를 손으로 만들어야 하고, 그것이 Part 1 에서 예고한 마찰의 청구서입니다. 실제로 돌아가는 인터프리터를 만들어 factorial(20)과 3장의 계좌 객체까지 우리 언어 위에서 실행했습니다.

[Read more]

Go 로 읽는 SICP Part 9: 채널은 SICP 스트림이 아니다

SICP 3.4 는 동시성을 사고 실험으로 다루는데, Go 에서는 실제로 돌릴 수 있습니다. 1000번의 인출 중 900건 가까이가 사라지는 것을 재현했고 go test -race 로 잡았습니다. 3.5 스트림은 반대입니다. 고루틴과 채널이 SICP 스트림처럼 보이지만 결정적으로 다릅니다. 스트림·채널·iter.Seq 를 같은 실험에 올려 세 가지가 어떻게 갈리는지 확인했습니다.

[Read more]

Go 로 읽는 SICP Part 8: 같은 pair 세 개를 세는 네 가지 답, 그리고 이벤트 루프

가변 데이터를 도입하면 공유가 생기고, 공유가 생기면 pair 세 개를 세는 답이 3·4·7·무한대로 갈립니다. SICP 연습문제 3.16 을 Go 로 재현하고, 같은 함정이 Go 슬라이스 append 에서 어떻게 나타나는지 실측했습니다. 후반부는 디지털 회로 시뮬레이터입니다. 원서와 같은 시각(8·11·16)을 재현했고 전가산기 진리표를 전수 검증했습니다.

[Read more]

Go 로 읽는 SICP Part 7: 시간이 들어오면 치환 모델이 무너진다

SICP 3장은 대입을 도입하고 그 대가를 절 하나를 써서 계산합니다. 치환 모델이 폐기되고 환경 모델이 들어옵니다. Go 클로저가 실제로 힙에 프레임을 만드는 것을 탈출 분석으로 확인했고, Go 1.22 의 루프 변수 변경이 정확히 이 프레임 이야기라는 것을 두 시맨틱을 나란히 실행해 보였습니다. 몬테카를로 예제에서는 난수 생성기 결함으로 π 가 2.72 로 나온 사고를 그대로 실었습니다.

[Read more]

Go 로 읽는 SICP Part 6: 1985년에 쓰인 Go 인터페이스 설계 지침

SICP 2.4~2.5 의 데이터 지향 프로그래밍은 Go 인터페이스 설계 이야기와 거의 같은 내용입니다. 명시적 디스패치·디스패치 테이블·메시지 패싱 세 가지를 Go 로 모두 구현하고, Go 인터페이스가 그중 어느 것인지 판정했습니다. 표현 문제(expression problem)는 컴파일 에러로 직접 확인했고, 제네릭 산술 타워에서 i×i 가 정수 -1 까지 내려오는 것도 재현했습니다.

[Read more]

Go 로 읽는 SICP Part 5: 파이프라인으로서의 프로그램, 그리고 quote 가 없는 언어

map, filter, accumulate 만으로 프로그램을 신호 처리 파이프라인처럼 조립하는 SICP 2.2.3 을 Go 로 옮기고, Go 1.23 의 iter.Seq 판과 나란히 놓았습니다. 여덟 퀸은 92개 해를 재현했습니다. 후반부는 기호 데이터입니다. Go 에 quote 가 없다는 사실이 여기서 처음으로 아프게 다가옵니다.

[Read more]

Go 로 읽는 SICP Part 4: 데이터란 무엇인가 — 저장 공간 없는 pair

SICP 2장은 데이터가 무엇인지 다시 묻습니다. 답은 “약속을 지키는 것이면 무엇이든 데이터"이고, 증거로 저장 공간이 전혀 없는 pair 를 클로저만으로 만들어 보입니다. Go 로 그대로 옮겨 봤고, 제네릭으로 옮기려다 Go 타입 시스템의 천장에 정확히 부딪혔습니다. 컴파일 에러를 그대로 실었습니다.

[Read more]

Go 로 읽는 SICP Part 3: 함수를 돌려주는 함수, 그리고 제네릭이 필요해지는 순간

SICP 1.3 은 프로시저를 인자로 넘기고 반환값으로 돌려주는 방법을 다룹니다. Go 로 옮기면 원서에 없던 것이 하나 생깁니다. 타입 시그니처입니다. 추상화의 계약이 눈에 보이고, 대신 코드가 길어집니다. 뉴턴법을 고정점 탐색으로 분해하고, 연습문제 1.45 의 평균 감쇠 횟수를 n=2부터 32까지 전부 측정했습니다.

[Read more]

Go 로 읽는 SICP Part 2: 프로시저는 재귀인데 프로세스는 반복이다

SICP 1장의 핵심은 코드의 모양과 실행의 모양이 다르다는 것입니다. 재귀적으로 생긴 프로시저가 반복적인 프로세스를 만들 수 있고, 그 구분이 성능을 가릅니다. 그런데 Go 에서는 이 구분이 통째로 지워집니다. 실측으로 확인하고, 왜 그런지와 무엇으로 대신할지를 정리했습니다. 페르마 소수 판정과 카마이클 수는 전수 검증했습니다.

[Read more]

Go 로 읽는 SICP Part 1: 마법사 책은 왜 아직도 살아 있나

1984년에 나온 프로그래밍 교재 하나가 40년이 지나도 계속 언급됩니다. SICP 는 어떤 책이고, 누가 썼고, MIT 는 왜 이 책으로 가르치던 과목을 스스로 폐지했는지 정리했습니다. 그리고 이 시리즈가 Scheme 대신 Go 를 쓰는 이유와, Go 로는 잘 안 되는 지점 세 곳을 실측 데이터와 함께 미리 밝혀 둡니다.

[Read more]

렉시오 CPU 플레이어 만들기 Part 6: 봇이 약한지 어떻게 아는가

Part 5 는 브라우저에서 한 판 돌려 찾은 결함을 고쳤습니다. 그 방법으로는 “조금 약하다"를 찾을 수 없어 시뮬레이터를 만들었더니, 도구가 전략을 재기도 전에 구현 버그부터 잡아냈습니다. 그리고 봇이 약한 이유를 세 번 틀리고 네 번째에 찾았습니다. 평가 함수는 처음부터 옳았고, 확률이 틀렸습니다.

[Read more]

렉시오 CPU 플레이어 만들기 Part 5: 봇이 아무것도 하지 않는 이유

Part 1~4 에서 설계한 렉시오 hard 봇을 실제로 구현했더니 봇이 거의 모든 턴을 패스했습니다. 개별 항은 전부 맞았고 항을 합치는 방식이 틀렸습니다. 평가 함수가 무너지는 네 가지 자리와, 그 회귀 테스트가 엉뚱한 이유로 통과한 이야기를 다룹니다.

[Read more]

달무티 CPU 플레이어 만들기 Part 4: 만들어 보니 hard 봇이 더 약했다

Part 1부터 3까지의 설계안을 실제로 구현해 시뮬레이션으로 재봤더니, hard 봇이 easy 봇보다 평균 0.6601등 나빴습니다. 무엇을 어떻게 쟀는지, 세 개의 구조 결함이 무엇이었는지, 어떤 고급 기능이 살아남았는지, 그리고 정정 후의 정식 검증 수치를 정리합니다.

[Read more]

렉시오 CPU 플레이어 만들기 Part 3: 손패 분해 플랜

렉시오 hard 봇이 자기 손패를 몇 번에 털 수 있는지 정확히 계산합니다. 유효 조합으로의 최소 분할을 비트마스크 DP 로 풀고, 탐욕법이 왜 다섯 번에 한 번꼴로 최적을 놓치는지, 그리고 DP 한 번이 왜 모든 후보의 평가까지 공짜로 끝내 주는지 다룹니다.

[Read more]

렉시오 CPU 플레이어 만들기 Part 2: 60비트 카운팅과 확실승수 판정

렉시오 hard 봇이 무엇을 아는지 다룹니다. 미공개 타일을 uint64 하나로 정확히 복원하고, 이 수를 아무도 못 받는다는 판정을 확률이 필요 없는 구조적 영역과 확률이 필요한 영역으로 나누며, 패스 로그를 비트마스크 제약으로 환산합니다.

[Read more]

렉시오 CPU 플레이어 만들기 Part 1: 타일 하나를 정수 하나로

렉시오(Lexio)를 디지털 게임으로 만들 때 CPU 플레이어를 어떻게 설계할지 다룹니다. Part 1 에서는 타일 60장을 정수 하나로 압축하는 표현을 잡고, 공식 룰의 비교 규칙을 정수 키 하나로 환원한 뒤, 결정적 규칙만으로 동작하는 easy 봇을 Go 코드로 구현합니다.

[Read more]

달무티 CPU 플레이어 만들기 Part 3: 수 평가와 전략적 패스

달무티 hard 봇이 실제로 어떤 수를 고르는지 다룹니다. 리드권 확보 확률과 가치를 분리한 수 평가 함수, 낼 수 있어도 참는 전략적 패스, 차단 의무의 정확한 조건, 세금과 혁명의 기대값 계산, 그리고 봇이 정말 세졌는지 재는 검증 방법을 Go 코드로 정리합니다.

[Read more]

달무티 CPU 플레이어 만들기 Part 2: hard 봇의 정보 모델과 확실승수 판정

달무티 hard 봇이 상대 손패를 훔쳐보지 않고 무엇을 알아낼 수 있는지 다룹니다. 오차 0의 카드 카운팅, 패스를 확정 정보가 아닌 확률적 증거로 다루는 법, 광대 2장이 만드는 구조적 확실승수 판정, 그리고 손패의 최소 제출 횟수 플랜을 재현 가능한 몬테카를로 수치와 함께 정리합니다.

[Read more]

달무티 CPU 플레이어 만들기 Part 1: 규칙 기반 easy 봇

달무티(The Great Dalmuti)를 디지털 게임으로 만들 때 CPU 플레이어를 어떻게 설계할지 다룹니다. Part 1 에서는 공정성 경계와 정책 인터페이스를 잡고, 결정적 규칙만으로 동작하는 easy 난이도 봇의 제출·패스·혁명·세금 정책을 Go 코드로 구현합니다.

[Read more]