Skip to content

Instantly share code, notes, and snippets.

@mattknox
Created November 17, 2010 19:56
Show Gist options
  • Save mattknox/703954 to your computer and use it in GitHub Desktop.
Save mattknox/703954 to your computer and use it in GitHub Desktop.
hamming numbers in haskell, common lisp and scheme
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