Hamming Numbers
module Enumerable def bop(op, m) map {|i| m.send(op, i)} end end class Array def | other return self + other if empty? or other.empty? case first <=> other.first when -1, 0; e = shift when 0, 1; e = other.shift end return (self | other).unshift(e) end end def hamming n (1..n/2).bop(:*,2) | (1..n/3).bop(:*,3) | (1..n/5).bop(:*,5) end hamming 30 #=> [2, 3, 4, 5, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28, 30]
Beware "|" operator hijacked and it works to merge streams
# "|" merge operator [3, 6, 9, 12] | [2, 4, 6, 8] #=> [2, 3, 4, 6, 8, 9, 12] "Adam".split(//) | "Eve".split(//) #=> ["A", "E", "d", "a", "m", "v", "e"]
Hint: Hamming Stream in Haskell
hamming = 1 : map (*2) hamming # map (*3) hamming # map (*5) hamming where xxs@(x:xs) # yys@(y:ys) | x==y = x : xs#ys | x<y = x : xs#yys | x>y = y : xxs#ys -- http://en.wikipedia.org/wiki/Haskell_programming_language#More_complex_examples
Another hint: 'fold'utilities
module Enumerable def foldl(o, m=nil) inject(m) {|m, i| m ? m.send(o, i) : i} end end (1..100).foldl(:+) #=> 5050 ('a'..'z').foldl(:+, ">") #=> ">abcdefghijklmnopqrstuvwxyz" # http://www.bigbold.com/snippets/tag/foldr