Skip to content

Instantly share code, notes, and snippets.

@yasuabe
Last active December 7, 2018 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yasuabe/ba9a04e67140dbfa56b2e0c60640be26 to your computer and use it in GitHub Desktop.
Save yasuabe/ba9a04e67140dbfa56b2e0c60640be26 to your computer and use it in GitHub Desktop.
import scala.collection.mutable
trait Prime4949Solver {
def primes: Stream[Int]
def is4949Prime(n: Int): Boolean = {
def loop(m: Int): Boolean = (m / 10, m % 10) match {
case (_, 4) | (_, 9) => true
case (0, _) => false
case (d, _) => loop(d)
}
loop(n)
}
def main(args: Array[String]): Unit = {
val n = args.head.toInt
println(primes.filter(is4949Prime).take(n).mkString(","))
}
}
object EratosthenesSieveSolver extends Prime4949Solver {
def sieve(limit: Int): Stream[Int] = {
val bs = mutable.BitSet(limit)
(2 to limit) foreach (bs += _)
(2 to math.sqrt(limit).toInt) foreach { n =>
(n * n to limit by n) foreach (bs -= _)
}
bs.toStream
}
override def primes = sieve(9999)
}
sealed trait PairingHeap {
def merge(another: PairingHeap): PairingHeap
}
case object Empty extends PairingHeap {
def merge(another: PairingHeap): PairingHeap = another
}
case class Tree(ns: Stream[Int], phs: List[PairingHeap]) extends PairingHeap {
private def join(t: Tree): PairingHeap =
if (ns.head <= t.ns.head) Tree(ns, t :: phs) else t.join(this)
def merge(another: PairingHeap): PairingHeap = another match {
case Empty => this
case t: Tree => join(t)
}
}
object PairingHeap {
def enqueue(ns: Stream[Int], q: PairingHeap): PairingHeap = Tree(ns, Nil) merge q
def mergeAll(phs: List[PairingHeap]): PairingHeap = phs match {
case Nil => Empty
case ph1 :: Nil => ph1
case ph1 :: ph2 :: pht => ph1 merge ph2 merge mergeAll(pht)
}
}
object WheelSieveSolver extends Prime4949Solver {
import PairingHeap._
private def spin(start: Int, wheel: Stream[Int]): Stream[Int] = {
def repeat: Stream[Int] = wheel append repeat
repeat.scan(start)(_ + _)
}
private def composites(ns: Stream[Int]): Stream[Int] = {
def loop(ms: Stream[Int]): Stream[Int] = (ns.head * ms.head) #:: loop(ms.tail)
loop(ns)
}
private def sieve(ns: Stream[Int], ph: PairingHeap): Stream[Int] = (ns, ph) match {
case (n #:: nt, Empty) => n #:: sieve(nt, enqueue(composites(ns), Empty))
case (n #:: nt, Tree(m #:: ms, qs)) =>
if (n < m) n #:: sieve(nt, enqueue(composites(ns), ph ))
else if (n > m) sieve(ns, enqueue(ms, mergeAll(qs)))
else sieve(nt, enqueue(ms, mergeAll(qs)))
}
override def primes: Stream[Int] = sieve(Stream(2, 3) append spin(5, Stream(2, 4)), Empty)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment