Hamming numbers

Revision as of 18:38, 2 December 2009 by rosettacode>Paddy3118 (New task and Python solutions)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Generate the sequence of hamming numbers, in increasing order.

Task
Hamming numbers
You are encouraged to solve this task according to the task description, using any language you may know.

Hamming numbers are numbers of the form:

   H = 2^i * 3^j * 5^k, 

Where i,j,k >= 0; and ^ is the power operator.

  1. Show the first twenty hamming numbers
  2. Show the 1690'th Hamming number. (the last one under 2^31)
  3. Show the one millionth Hamming number

Python

<lang python>from itertools import islice

def hamming2():

   \
   This version is based on a snippet from:
       http://dobbscodetalk.com/index.php?option=com_content&task=view&id=913&Itemid=85
       When expressed in some imaginary pseudo-C with automatic
       unlimited storage allocation and BIGNUM arithmetics, it can be
       expressed as:
           hamming = h where
             array h;
             n=0; h[0]=1; i=0; j=0; k=0;
             x2=2*h[ i ]; x3=3*h[j]; x5=5*h[k];
             repeat:
               h[++n] = min(x2,x3,x5);
               if (x2==h[n]) { x2=2*h[++i]; }
               if (x3==h[n]) { x3=3*h[++j]; }
               if (x5==h[n]) { x5=5*h[++k]; } 
   
   h = 1
   _h=[h]    # memoized
   multipliers  = (2, 3, 5)
   multindeces  = [0 for i in multipliers] # index into _h for multipliers
   multvalues   = [x * _h[i] for x,i in zip(multipliers, multindeces)]
   yield h
   while True:
       h = min(multvalues)
       _h.append(h)
       for (n,(v,x,i)) in enumerate(zip(multvalues, multipliers, multindeces)):
           if v == h:
               i += 1
               multindeces[n] = i
               multvalues[n]  = x * _h[i]
       # cap the memoization
       mini = min(multindeces)
       if mini >= 1000:
           del _h[:mini]
           multindeces = [i - mini for i in multindeces]
       #
       yield h</lang>

Sample output:

>>> list(islice(hamming2(), 20))
[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36]
>>> list(islice(hamming2(), 1690, 1691))
[2125764000]
>>> list(islice(hamming2(), 1000000, 1000001))
[519381797917090766274082018159448243742493816603938969600000000000000000000000000000]
>>>