- 해스켈 수도쿠 살버
Tweet
- Game Development
- 2011/05/23 22:15
- Functional language, haskell, monad, Python, sudoku, 모나드, 수도쿠, 함수형 언어
-
얼마 전, Clojure & Python, Side by Side 글을 보고 나도 수도쿠(참고1) 살버를 해스켈로 포팅해보자 마음 먹었습니다. 먼저 원 고안자인 Peter Norvig의 글(참고2)을 읽고 찬찬히 읽고 알고리즘을 이해했습니다. 알고리즘을 특별히 함수형 언어에 적절하게 바꾸거나 하지 않고 그대로 포팅할 작정이었으므로, 기껏해야 네다섯 시간 투자하면 되겠거니 생각했습니다... 실제로는 투자한 시간을 합쳐보니 총 24시간은 넘을듯 하더군요;
- 일단, 여기 최종 해스켈 코드
코드보기
- 결과
원 파이썬 코드는 214행이었습니다. 제 해스켈 코드는 276행이군요. 원 노빅씨의 해법이 상당히 간결하다고 봤을 때, 나쁘지 않다고 봅니다.
성능은 다음처럼 나왔습니다. 보시다시피, 해스켈 버전이 약간 느리군요. 그래도 첫 시도로는 준수한 결과라 봅니다;
- 배운 것
- 수도쿠(참고1) 퍼즐 푸는 알고리즘, 노빅씨가 잘 설명해놓으셨습니다(참고2).
- 노빅씨의 파이썬 해법(참고2), 아름답습니다. (물론, 저는 파이썬 전문가 아닙니다;)
- 두 언어가 거의 동일하게 list comprehension(참고3)을 지원해서 편했습니다.
- C++에서와 같은 의미의 변수가 없다는 사실이 생각만큼 큰 차이로 느껴지지 않더군요.
- 후글(http://haskell.org/hoogle/)과 구글이 없었다면 24시간 정도만에 어림도 없었습니다.
- 기존 C 스타일의 언어에서 너무 익숙한 반복문과 반복문 내에서의 이른 탈출이 아예 없다는 것이 포팅에서의 가장 큰 걸림돌이었습니다.
- 함수형 언어에서는 반복이 아닌 재귀로 생각해야 합니다.
- 혹은 한단계 더 나아가 fold와 monad(참고5)로 생각해야 합니다.
- 해스켈에는 fold가 참 많습니다. foldl, foldr, foldl' 그리고 foldr'. 어떤 놈을 써야 할지 많이 헷갈리더군요(참고4).
- 이해하기 까다롭기로 소문난 모나드(참고5)가 자연스럽게 필요하게 되더군요. 이 놈 없으면 과도하게 중첩된 case 문을 사용하게 됩니다.
- 해스켈이 type inference를 지원하여 필수 사항은 아님에도, 형 선언을 꼬박꼬박 해주는게 이해하는데도 그렇고 디버깅 시에도 도움이 많이 되더군요.
- 책에서 읽은대로, 정말 해스켈로 짤 때에는, 컴파일이 되면 보통 바로 그대로 문제없이 동작하더군요. 물론, 컴파일이 되게 하기가 저한테는 쉽지 않았습니다만;
- IO 모나드에서 do 용법은 해스켈에서 일반 순수 함수를 짤 때와는 정말 다른 느낌이더군요. 흡사 다른 언어인 것처럼...;
- 해스켈의 특징인 laziness가 또 머리를 더 복잡하게 합니다. (제 코드에서 볼 수 있는 것처럼, 특정 상황에서는 결과를 얻기 위해 strict 계산을 강제해야 했습니다.)
- 결론
- 해스켈은 imperative programming language와는 완전 다른 세상이다...
- 해스켈 책 하나(제 경우는 "Real World Haskell"(참고9)) 읽은 것으로는, 해스켈로 적절히 코딩하기 힘들다. (파이썬 배울 때랑은 다르던군요.)
- 제 코드 분명 최선과는 거리가 멀겁니다. 노빅씨의 알고리즘을 그래도 포팅한다는 제약 조건 하에서도 분명 더 우아한 해법이 존재할겁니다. 그 제약 조건이 없으면, 물론 훨씬 다양한 해법이 존재하겠죠(참고10).
- 시간이 참 많이 걸렸지만, 그래도 유익한 코딩 연습이었다고 생각합니다. ^^
- 참고자료
- Sudoku - Wikipedia: https://secure.wikimedia.org/wikipedia/en/wiki/Sudoku
- Solving Every Sudoku Puzzle: http://norvig.com/sudoku.html
- List comprehension - Wikipedia: https://secure.wikimedia.org/wikipedia/en/wiki/List_comprehension
- Implications of foldr vs. foldl (or foldl'): http://stackoverflow.com/questions/384797/implications-of-foldr-vs-foldl-or-foldl
- Monads for the Curious Programmer: http://bartoszmilewski.wordpress.com/2011/01/09/monads-for-the-curious-programmer-part-1/ http://bartoszmilewski.wordpress.com/2011/03/14/monads-for-the-curious-programmer-part-2/ http://bartoszmilewski.wordpress.com/2011/03/17/monads-for-the-curious-programmer-part-3/
- Functional Programming For Beginners: http://ontwik.com/scala/functional-programming-for-beginners/
- A Taste Of Haskell: http://ontwik.com/haskell/simon-peyton-jones-a-taste-of-haskell/
- Learn You a Haskell for Great Good!: http://learnyouahaskell.com/
- Real World Haskell: http://book.realworldhaskell.org/
- Sudoku - HaskellWiki: http://www.haskell.org/haskellwiki/Sudoku
- Haskell Cheat Sheet: http://blog.codeslower.com/static/CheatSheet.pdf
본 글의 영문 버전을 #AltDevBlogADay에 "Sudoku Solver in Haskell"로 게시하였습니다.
'Game Development' 카테고리의 다른 글
| 퍼포스 changelist 로그로 검색하기 (0) | 2011/08/23 |
|---|---|
| SIKULI를 이용한 GUI 테스트 자동화 (1) | 2011/06/22 |
| 해스켈 수도쿠 살버 (0) | 2011/05/23 |
| 자료구조에서 사이클 찾아내기 (0) | 2011/01/18 |
| 뒤늦게 올리는 GDC 2010 리포트 (5) | 2010/04/28 |
| [해외 개발자 인터뷰] Tiago Sousa (4) | 2010/02/17 |











Recent comment