RosettaCodeData/Task/Hamming-numbers/Icon/hamming-numbers.icon
Ingy döt Net db842d013d A-M baby
2013-04-10 21:29:02 -07:00

53 lines
1.7 KiB
Text

# 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