# Lazily generate the three Hamming numbers that can be derived directly # from a known Hamming number h class Triplet : Class (cv, ce) method nextVal() suspend cv := @ce end initially (baseNum) cv := 2*baseNum ce := create (3|5)*baseNum end # Generate Hamming numbers, in order. Default is first 30 # But an optional argument can be used to generate more (or less) # e.g. hamming 5000 generates the first 5000. procedure main(args) limit := integer(args[1]) | 30 every write("\t", generateHamming() \ limit) end # Do the work. Start with known Hamming number 1 and maintain # a set of triplet Hamming numbers as they get derived from that # one. Most of the code here is to figure out which Hamming # number is next in sequence (while removing duplicates) procedure generateHamming() triplers := set() insert(triplers, Triplet(1)) suspend 1 repeat { # Pick a Hamming triplet that *may* have the next smallest number t1 := !triplers # any will do to start every t1 ~=== (t2 := !triplers) do { if t1.cv > t2.cv then { # oops we were wrong, switch assumption t1 := t2 } else if t1.cv = t2.cv then { # t2's value is a duplicate, so # advance triplet t2, if none left in t2, remove it t2.nextVal() | delete(triplers, t2) } } # Ok, t1 has the next Hamming number, grab it suspend t1.cv insert(triplers, Triplet(t1.cv)) # Advance triplet t1, if none left in t1, remove it t1.nextVal() | delete(triplers, t1) } end