blue-sky
blue-sky

Reputation: 53876

Get list of primes to N

I'm trying to write a function which takes an Int and returns all of the prime numbers up to and including that Int.

for example "list of primes for 8" = List(3,5,7)

This is what I have so far :

  def isPrime(i: Int): Boolean = {
    if (i <= 1)
      false
    else if (i == 2)
      true
    else
      !(2 to (i - 1)).exists(x => i % x == 0)
  }                                               //> isPrime: (i: Int)Boolean

    def getListOfPrimesToN(n : Int) = {

    }

for the function getListOfPrimesToN I plan to 1. create a List "l" of size n and populate it with elements ranging from 0 to n. 2. call map function of "l" and call isPrime for each element in List.

How to create the List of element 1 to N ?

Any alternative solutions for returning all of the prime numbers up to and including an Int N welcome.

Upvotes: 5

Views: 6417

Answers (4)

madooc
madooc

Reputation: 89

How about this.

def getPrimeUnder(n: Int) = {
  require(n >= 2)
  val ol = 3 to n by 2 toList // oddList
  def pn(ol: List[Int], pl: List[Int]): List[Int] = ol match {
    case Nil => pl
    case _ if pl.exists(ol.head % _ == 0) => pn(ol.tail, pl)
    case _ => pn(ol.tail, ol.head :: pl)
  }
  pn(ol, List(2)).reverse
}

Upvotes: 0

Apocalisp
Apocalisp

Reputation: 35054

You can solve this with infinite streams. If you had a stream primes of all the primes, you could just say primes.takeWhile(_ <= n) to get the primes up to and including n.

To get all the primes, you start with a stream of all the numbers starting from 2, the first prime. You can then skip all the even numbers since those are definitely not prime. Then you can skip all the other numbers that are not prime.

val primes = 2 #:: Stream.from(3,2).filter(isPrime)

Now you just need isPrime to check if a given number is prime. A number is prime if it is not divisible by any smaller prime. We actually need only consider primes whose square is not greater than the number (since, logically, a composite number's smallest prime factor can't be larger than its square root).

def isPrime(n: Int): Boolean =
  primes.takeWhile(p => p*p <= n).forall(n % _ != 0)

Check this in the REPL:

scala> primes.takeWhile(_ <= 8).toList
res0: List[Int] = List(2, 3, 5, 7)

Caveat: This only works for positive numbers smaller than Integer.MAX_VALUE.

Upvotes: 7

elm
elm

Reputation: 20415

An implementation of the Sieve of Eratosthenes algorithm for efficiently finding prime numbers up to a given value N includes the following, (fixed and improved on this SO answer),

implicit class Sieve(val N: Int) extends AnyVal {
  def primesUpTo() = {
    val isPrime = collection.mutable.BitSet(2 to N: _*) -- (4 to N by 2)
    for (p <- 2 +: (3 to Math.sqrt(N).toInt by 2) if isPrime(p)) {
      isPrime --= p*p to N by p
    }
    isPrime.toImmutable
  }
} 

Hence

10.primesUpTo.toList
res: List(2, 3, 5, 7)

11.primesUpTo.toList
res: List(2, 3, 5, 7, 11)

Note Find prime numbers using Scala. Help me to improve for additional ideas and discussion.

Upvotes: 6

Eastsun
Eastsun

Reputation: 18869

Here is the code based on your:

scala> def isPrime(n: Int): Boolean =
     |   n >= 2 && (2 to math.sqrt(n).toInt).forall(n%_ != 0)
isPrime: (n: Int)Boolean

scala> def getListOfPrimesToN(n: Int): List[Int] = 
     |   List.range(2, n+1) filter isPrime
getListOfPrimesTON: (n: Int)List[Int]

scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)

Here is another solution using Stream:

scala> def getListOfPrimesToN(n: Int): List[Int] = {
     |   lazy val ps: Stream[Int] = 2 #:: Stream.from(3)
                 .filter(x => ps.takeWhile(p => p*p <= x).forall(x%_ != 0))
     |   ps.takeWhile(_ <= n).toList
     | }
getListOfPrimesToN: (n: Int)List[Int]

scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)

Upvotes: 0

Related Questions