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