Search code examples
kotlinsequenceprimeslazy-sequences

This prime generating function using generateSequence in Kotlin is not easy to understand. :(


val primes = generateSequence(2 to generateSequence(3) {it + 2}) {
  val currSeq = it.second.iterator()
  val nextPrime = currSeq.next()
  nextPrime to currSeq.asSequence().filter { it % nextPrime != 0}
}.map {it.first}
println(primes.take(10).toList()) // prints [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

I tried to understand this function about how it works, but not easy to me. Could someone explain how it works? Thanks.


Solution

  • It generates an infinite sequence of primes using the "Sieve of Eratosthenes" (see here: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes).

    This implementation uses a sequence of pairs to do this. The first element of every pair is the current prime, and the second element is a sequence of integers larger than that prime which is not divisible by any previous prime.

    It starts with the pair 2 to [3, 5, 7, 9, 11, 13, 15, 17, ...], which is given by 2 to generateSequence(3) { it + 2 }. Using this pair, we create the next pair of the sequence by taking the first element of the sequence (which is now 3), and then removing all numbers divisible by 3 from the sequence (removing 9, 15, 21 and so on). This gives us this pair: 3 to [5, 7, 11, 13, 17, ...]. Repeating this pattern will give us all primes.

    After creating a sequence of pairs like this, we are finally doing .map { it.first } to pick only the actual primes, and not the inner sequences.

    The sequence of pairs will evolve like this:

    2 to [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, ...]
    3 to [5, 7, 11, 13, 17, 19, 23, 25, 29, ...]
    5 to [7, 11, 13, 17, 19, 23, 29, ...]
    7 to [11, 13, 17, 19, 23, 29, ...]
    11 to [13, 17, 19, 23, 29, ...]
    13 to [17, 19, 23, 29, ...]
    // and so on