RosettaCodeData/Task/Prime-decomposition/Scala/prime-decomposition-1.scala
2015-02-20 00:35:01 -05:00

43 lines
1.6 KiB
Scala
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import annotation.tailrec
import collection.parallel.mutable.ParSeq
object PrimeFactors extends App {
def factorize(n: Long): List[Long] = {
@tailrec
def factors(tuple: (Long, Long, List[Long], Int)): List[Long] = {
tuple match {
case (1, _, acc, _) => acc
case (n, k, acc, _) if (n % k == 0) => factors((n / k, k, acc ++ ParSeq(k), Math.sqrt(n / k).toInt))
case (n, k, acc, sqr) if (k < sqr) => factors(n, k + 1, acc, sqr)
case (n, k, acc, sqr) if (k >= sqr) => factors((1, k, acc ++ ParSeq(n), 0))
}
}
factors((n, 2, List[Long](), Math.sqrt(n).toInt))
}
def mersenne(p: Int): BigInt = (BigInt(2) pow p) - 1
def sieve(nums: Stream[Int]): Stream[Int] =
Stream.cons(nums.head, sieve((nums.tail) filter (_ % nums.head != 0)))
// An infinite stream of primes, lazy evaluation and memo-ized
val oddPrimes = sieve(Stream.from(3, 2))
def primes = sieve(2 #:: oddPrimes)
oddPrimes takeWhile (_ <= 59) foreach { p =>
{ // Needs some intermediate results for nice formatting
val numM = s"M${p}"
val nMersenne = mersenne(p).toLong
val lit = f"${nMersenne}%30d"
val datum = System.nanoTime
val result = factorize(nMersenne)
val mSec = ((System.nanoTime - datum) / 1.0e+6).round
def decStr = { if (lit.length > 30) f"(M has ${lit.length}%3d dec)" else "" }
def sPrime = { if (result.isEmpty) " is a prime number." else "" }
println(
f"$numM%4s = 2^$p%03d - 1 = ${lit}%s${sPrime} ($mSec%,4d msec) composed of ${result.mkString(" × ")}")
}
}
}