Skip to content

Instantly share code, notes, and snippets.

@emlyn
Last active March 23, 2016 23:24
Show Gist options
  • Save emlyn/e763f3321350179b392b to your computer and use it in GitHub Desktop.
Save emlyn/e763f3321350179b392b to your computer and use it in GitHub Desktop.
Generate unbounded lazy sequence of primes in Clojure (and unbounded iterator of primes in Python)
#!/usr/bin/env inlein
'{:dependencies [[org.clojure/clojure "1.8.0"]]
:jvm-opts []}
;; to run, use inlein: https://github.com/hyPiRion/inlein (or paste into a repl)
(defn primes
"Generate a lazy infinite sequence of primes, using method from (improved to skip even numbers):
https://web.archive.org/web/20150710134640/http://diditwith.net/2009/01/20/YAPESProblemSevenPart2.aspx"
([]
(cons 2 (primes 3 {})))
([candidate state]
;; state is a map of next composites above candidate to prime factors (for primes < candidate)
(if-let [factors (state candidate)]
;; candidate is composite, recur with updated state
(recur (+ 2 candidate)
(reduce (fn [s factor]
;; add twice the prime factor to the candidate because both are odd,
;; so we skip the next multiple which will necessarily be even:
(update-in s [(+ candidate factor factor)] conj factor))
(dissoc state candidate)
factors))
;; candidate is prime, add it to lazy seq and recurse with updated state:
(lazy-seq (cons candidate (primes (+ 2 candidate)
;; start at candidate squared (because smaller composites will necessarily
;; also have smaller prime factors, so will be caught by earlier primes):
(assoc state (* candidate candidate) [candidate]))))))))
(println "The first few primes are" (take 40 (primes)))
(println "The hundred-thousandth prime is" (first (drop 99999 (primes))))
from collections import defaultdict
from itertools import islice
def primes():
"""Generate an infinite sequence of primes, using method from (improved to skip even numbers):
https://web.archive.org/web/20150710134640/http://diditwith.net/2009/01/20/YAPESProblemSevenPart2.aspx"""
yield 2
candidate = 3
# state is a map of next composites above candidate to prime factors (for primes < candidate)
state = defaultdict(list)
while True:
if candidate in state:
# candidate is composite, update state and loop
for factor in state[candidate]:
# add twice the prime factor to the candidate because bot are odd,
# so we skip the next multiple which will necessarily be even:
state[candidate + factor + factor].append(factor)
del state[candidate]
candidate += 2
else:
# candidate is prime, yield it and update state
yield candidate
# start at candidate squared (because smaller composites will necessarily
# also have smaller prime factors, so will be caught by earlier primes):
state[candidate * candidate] = [candidate]
candidate += 2
print 'The first few primes are', list(islice(primes(), 40))
print 'The hundred-thousandth prime is', next(islice(primes(), 99999, None))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment