Hamming numbers are numbers of the form  

    H = 2i × 3j × 5k
           where 
     i,  j,  k  ≥  0 

Hamming numbers   are also known as   ugly numbers   and also   5-smooth numbers   (numbers whose prime divisors are less or equal to 5).



Task

Generate the sequence of Hamming numbers, in increasing order.   In particular:

 Show the   first twenty   Hamming numbers.
 Show the   1691st   Hamming number (the last one below   231).
 Show the   one millionth   Hamming number (if the language – or a convenient library – supports arbitrary-precision integers).


Related tasks

 Humble numbers
 N-smooth numbers


References

 Wikipedia entry:   Hamming numbers     (this link is re-directed to   Regular number).
 Wikipedia entry:   Smooth number
 OEIS entry:   A051037   5-smooth   or   Hamming numbers
 Hamming problem from Dr. Dobb's CodeTalk (dead link as of Sep 2011; parts of the thread here and here).


 
//
// How to compile:
// patscc -DATS_MEMALLOC_LIBC -o hamming hamming.dats
//
#include
"share/atspre_staload.hats"
 
fun
min3
(
  A: arrayref(int, 3)
) : natLt(3) = i where
{
  var x: int = A[0]
  var i: natLt(3) = 0
  val () = if A[1] < x then (x := A[1]; i := 1)
  val () = if A[2] < x then (x := A[2]; i := 2)
} (* end of [min3] *)
 
fun
hamming
{n:pos}
(
  n: int(n)
) : int = let
//
var A = @[int](2, 3, 5)
val A = $UNSAFE.cast{arrayref(int, 3)}(addr@A)
var I = @[int](1, 1, 1)
val I = $UNSAFE.cast{arrayref(int, 3)}(addr@I)
val H = arrayref_make_elt<int> (i2sz(succ(n)), 0)
val () = H[0] := 1
//
fun
loop{k:pos}
  (k: int(k)) : void =
(
//
if
k < n
then let
  val i = min3(A)
  val k =
  (
    if A[i] > H[k-1] then (H[k] := A[i]; k+1) else k
  ) : intBtwe(k, k+1)
  val ii = I[i]
  val () = I[i] := ii+1
  val ii = $UNSAFE.cast{natLte(n)}(ii)
  val () = if i = 0 then A[i] := 2*H[ii]
  val () = if i = 1 then A[i] := 3*H[ii]
  val () = if i = 2 then A[i] := 5*H[ii]
in
  loop(k)
end // end of [then]
else () // end of [else]
//
) (* end of [loop] *)
//
in
  loop (1); H[n-1]
end (* end of [hamming] *)
 
implement
main0 () =
{
val () =
loop(1) where
{
fun
loop
{n:pos}
(
  n: int(n)
) : void =
if
n <= 20
then let
  val () =
  println! ("hamming(",n,") = ", hamming(n))
in
  loop(n+1)
end // end of [then]
// end of [if]
} (* end of [val] *)
val n = 1691
val () = println! ("hamming(",n,") = ", hamming(n))
//
} (* end of [main0] *)
 