Skip to content

Instantly share code, notes, and snippets.

@akihiro4chawon
Created April 24, 2011 05:44
Show Gist options
  • Save akihiro4chawon/939355 to your computer and use it in GitHub Desktop.
Save akihiro4chawon/939355 to your computer and use it in GitHub Desktop.
Hamming's Problem in scala
object Main {
def humming: Iterator[BigInt] = {
object ForwardReferenceable {
def output: Iterator[BigInt] = Iterator(BigInt(3), BigInt(4), BigInt(5)) ++ merged
val Seq(result, m2, m3, m5) = tee(output, 4)
val merged = merge(m2 map {_ * 2}, m3 map {_ * 3}, m5 map {_ * 5})
}
Iterator(BigInt(1), BigInt(2)) ++ ForwardReferenceable.result
}
def main(args: Array[String]) {
humming take 10 foreach println
assert((humming take 20 toSeq) == Seq(1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36))
assert((humming drop 1690 next) == BigInt("2125764000"))
//assert((humming drop 1000000-1 next) == BigInt("519312780448388736089589843750000000000000000000000000000000000000000000000000000000"))
}
def tee[T](itr: Iterator[T], n: Int): Seq[Iterator[T]] =
Seq.iterate(itr.duplicate, n){_._2.duplicate} map {_._1}
def merge[T: Ordering](streams: Iterator[T]*): Iterator[T] = {
def lookAheadMerge(heads: Seq[T], tails: Seq[Iterator[T]]): Iterator[T] = {
val min = heads.min
val newHeads = (heads zip tails) collect { case (head, tail) if tail.hasNext =>
if (head == min) tail.next else head
}
// // if you are sure the itarator has infinite elements,
// // you need not to check if the iterator `hasNext` element...
// val newHeads = (heads zip tails) map { case (head, tail) =>
// if (head == min) tail.next else head
// }
Iterator(min) ++ lookAheadMerge(newHeads, tails)
}
lookAheadMerge(streams map {_.next}, streams)
}
}
object Main {
// lazy stream of Hamming sequence
val hamming: Stream[BigInt] = BigInt(1) #:: merge(Seq(2, 3, 5) map {n => hamming map {_ * n}})
def merge[T: Ordering](streams: Seq[Stream[T]]): Stream[T] = {
val min = streams.map(_.head).min
min #:: merge(streams map {s => if (s.head == min) s.tail else s})
}
def main(args: Array[String]) {
println(hamming take 10) // lazy..
println(hamming take 10 mkString ",") // evaluate first 10 terms
assert(hamming.take(20) == Stream(1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36))
assert(hamming(1690) == BigInt("2125764000"))
//assert(hamming(1000000-1) == BigInt("519312780448388736089589843750000000000000000000000000000000000000000000000000000000"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment