#lang racket
(require math/number-theory)
;;takes about 4 seconds
(apply + (filter prime? (range 1 2000000)))
But I thought that spoiled the fun, and I was surely making racket work more
then necessary testing each number in the range, so I thought the Sieve of
Eratosthenes would be fast and fun:
#lang racket
;; Input: an integer n > 1
(define (sieve-of-eratosthenes n)
;; Let A be an array of Boolean values, indexed by integers 2 to n,
;; initially all set to true.
;; for i = 2, 3, 4, ..., √n :
;; when A[i] is true:
;; for j = i², i²+i, i²+2i, ..., n:
;; A[j] := false
(define A (make-vector n #t))
(for ([i (range 2 (sqrt n))])
(when (vector-ref A i)
(for ([p (range 0 n)])
#:break (> (+ (* i i) (* p i) 1) n)
(let ([j (+ (* i i) (* p i))])
(vector-set! A j #f)))))
;; Now all i such that A[i] is true are prime.
(filter number?
(for/list ([i (range 2 n)])
(when (vector-ref A i) i))))
;;takes about 17 seconds
(time (apply + (sieve-of-eratosthenes 2000000))
But it is dead slow....
Thanks,
Jordan
____________________
Racket Users list:
http://lists.racket-lang.org/users
I'm working through some programing puzzles, and one of them was to find the sum of all primes less the 2 million, the new math/number-theory collection (thanks Neil) makes it easy:
#lang racket
(require math/number-theory)
;;takes about 4 seconds
(apply + (filter prime? (range 1 2000000)))
But I thought that spoiled the fun, and I was surely making racket work more
then necessary testing each number in the range, so I thought the Sieve of
Eratosthenes would be fast and fun:
(define (sieve-of-eratosthenes n)
(define A (make-vector n #t))
But it is dead slow....
http://docs.racket-lang.org/guide/for.html#(part._for-performance)
Filtering the final list during building is also an improvement:
(for/list ([i (range 2 n)]
#:when (vector-ref A i))
i)
And let's make it more consistent with the comment style, and consistent
with the above changes. This appears to speed it up even more, although
I didn't investigate where exactly the big win(s) were:
#lang racket
;; Input: an integer n > 1
(define (sieve-of-eratosthenes n)
;; Let A be an array of Boolean values, indexed by integers 2 to n,
;; initially all set to true.
;; for i = 2, 3, 4, ..., √n :
;; when A[i] is true:
;; for j = i², i²+i, i²+2i, ..., n:
;; A[j] := false
(define A (make-vector n #t))
(for ([i (in-range 2 (sqrt n))]
#:when (vector-ref A i))
(for ([j (in-range (sqr i) n i)])
(vector-set! A j #f)))
;; Now all i such that A[i] is true are prime.
(for/list ([i (in-range 2 n)]
#:when (vector-ref A i))
i))
(time (apply + (sieve-of-eratosthenes 2000000)))
Compare:
> (time (apply + (filter prime? (range 2 n))))
cpu time: 9788 real time: 9974 gc time: 1851
142913828922
> (time (apply + (soe n)))
cpu time: 1049 real time: 1065 gc time: 311
142913828922
> (time (apply + (sieve-of-eratosthenes n)))
cpu time: 266955 real time: 274532 gc time: 218362
142913828922
Machine info in separate email to the list.
> In the number-theory module I used remainders modulo 60=2*2*3*5.
> The trick is that there are exactly 16 numbers modulo 60, that
> stems from non-primes. One can therefore represent the block of 60
> remainders in only 2 bytes. See the gory details in:
>
> https://github.com/plt/racket/blob/master/collects/math/private/number-theory/small-primes.rkt
I looked at that for quite a while (it is wonderful that so much of racket is
written in racket) but never quite "got it" I think that method is called the
Atkin Sieve? As I said it is still over my head, but it seems like their would
be a straight forward way to provide your sieve from that module?
On 24 Apr 2013 10:42, "Shannon Severance" <s...@s53.me> wrote:
> (define sqrt-n (inexact->exact (ceiling(sqrt n))))
Racket has integer-sqrt, which saves you defining sqrt-n every time.
Also worth noting is sqr, which covers the occasions you want (* x x) or
(expt x 2)
Customer testimonial:
> I have used integer-sqrt in lots of Project Euler problems. It has never let me down!
> - Tim, Epsom
--
sent from my phone
consider yourself lucky if you get
all the right letters in the right order