My solution isn’t very long, but the machinery behind the scenes is rather
extensive. In an effort to save memory, I’ve tried to make heavy use of
iterators—sort of like lazy evaluation of lists in Haskell. Below is what I
wrote for this exercise; I also used an implementation of the Sieve of
Eratosthenes for primes and a Miller-Rabin primality test.
The full code is available here.