Created
November 17, 2010 19:56
-
-
Save mattknox/703954 to your computer and use it in GitHub Desktop.
hamming numbers in haskell, common lisp and scheme
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
main = print (take 1000 hamming) | |
hamming = 1 : map (2*) hamming ~~ map (3*) hamming ~~ map (5*) hamming | |
where | |
xxs@(x:xs) ~~ yys@(y:ys) -- To merge two streams: | |
| x==y = (x : xs~~ys) -- if the heads are common, take that | |
| x<y = (x : xs~~yys) -- otherwise, take the smaller one | |
| x>y = (y : xxs~~ys) -- and proceed to merge the rest | |
(defun n-hammings (twos threes fives tail n out) | |
(if (= n 0) | |
out | |
(let* ((2l (* 2 (car twos))) | |
(3l (* 3 (car threes))) | |
(5l (* 5 (car fives))) | |
(next (min 2l 3l 5l))) | |
(progn (setf (cdr tail) (cons next ())) | |
(let ((out2 (if (= next 2l) (cdr twos) twos)) | |
(out3 (if (= next 3l) (cdr threes) threes)) | |
(out5 (if (= next 5l) (cdr fives) fives))) | |
(n-hammings out2 out3 out5 (cdr tail) (1- n) out)))))) | |
(defun n-hamming-nums (n) | |
(let ((res (list 1))) | |
(n-hammings res res res res n res) | |
(nth n res))) | |
;; scheme | |
(define (n-hammings twos threes fives tail n out) | |
(if (= n 0) | |
out | |
(let* ((2l (* 2 (car twos))) | |
(3l (* 3 (car threes))) | |
(5l (* 5 (car fives))) | |
(next (min 2l 3l 5l))) | |
(set-cdr! tail (cons next ())) | |
(let* ((out2 (if (= next 2l) (cdr twos) twos)) | |
(out3 (if (= next 3l) (cdr threes) threes)) | |
(out5 (if (= next 5l) (cdr fives) fives))) | |
(n-hammings out2 out3 out5 (cdr tail) (-- n) out))))) | |
(define (n-hamming-nums n) | |
(let ((res (list 1))) | |
(n-hammings res res res res n res) | |
(list-ref res n))) | |
; the only differences in CL and scheme here are that you need to define | |
; -- , and that set-cdr! instead of setf is required. I prefer the | |
; greater level of abstraction of setf, but it is not important. | |
; relative to haskell, this takes 2x as much code, in this case | |
; because I had to manually simulate lazy lists. Interestingly, I | |
; posted this example to CLL, and no one was able to produce a | |
; shorter version that was also O(n) (search hamming on CLL to see | |
; the discussion). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment