-
Notifications
You must be signed in to change notification settings - Fork 255
/
primes.rkt
149 lines (128 loc) · 4.26 KB
/
primes.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#lang racket/base
(require racket/os racket/fixnum racket/tcp racket/unsafe/ops racket/vector racket/list data/queue
(rename-in racket/unsafe/ops
[unsafe-vector*-ref vector-ref]
[unsafe-vector*-set! vector-set!]
[unsafe-vector*-length vector-length]
[unsafe-fx+ +]
[unsafe-fx- -]
[unsafe-fxmodulo modulo]
[unsafe-fx* *]
[unsafe-fx< <]
[unsafe-fx> >]
[unsafe-fx>= >=]
[unsafe-fx<= <=]
[unsafe-fx= =]))
(#%declare #:unsafe)
(struct Node (children terminal)
#:mutable
#:authentic)
(struct Sieve (limit [prime #:mutable])
#:authentic
#:guard (lambda (limit prime type-name)
(values limit (make-vector (+ limit 1) #f))))
(define (calc sieve)
(define limit (+ (Sieve-limit sieve)))
(define prime (Sieve-prime sieve))
(define (to-list)
(vector-set*! prime 2 #t 3 #t)
(for/list ([p (in-range 2 (+ limit 1))]
#:when (vector-ref prime p))
p))
(define (omit-squares)
(let loop ([r 5])
(define sq (* r r))
(cond
[(>= sq limit) r]
[else (when (vector-ref prime r)
(let loop ([i sq])
(cond
[(>= i limit) i]
[else (vector-set! prime i #f)
(loop (+ i sq))])))
(loop (+ r 1))])))
(define (step1 x y)
(let ([n (+ (* 4 x x) (* y y))])
(when (and (<= n limit) (or (= (modulo n 12) 1) (= (modulo n 12) 5)))
(vector-set! prime n (not (vector-ref prime n))))))
(define (step2 x y)
(let ([n (+ (* 3 x x) (* y y))])
(when (and (<= n limit) (= (modulo n 12) 7 ))
(vector-set! prime n (not (vector-ref prime n))))))
(define (step3 x y)
(let ([n (- (* 3 x x) (* y y))])
(when (and (> x y) (<= n limit) (= (modulo n 12) 11))
(vector-set! prime n (not (vector-ref prime n))))))
(define (loop-y x)
(let loop ([y 1])
(cond
[(< (* y y) limit)
(step1 x y)
(step2 x y)
(step3 x y)
(loop (+ y 1))]
[else y])))
(define (loop-x)
(let loop ([x 1])
(cond
[(< (* x x) limit)
(loop-y x)
(loop (+ x 1))]
[else x])))
(loop-x)
(omit-squares)
(to-list))
(define (generate-trie primes)
(define root (Node (make-hasheq) #f))
(for ([el (in-list primes)])
(define head root)
(define children (Node-children head))
(define el-str (number->string el))
(define el-str-len (string-length el-str))
(for ([ch (in-string el-str)])
(set! head (hash-ref! (Node-children head) ch (Node (make-hasheq) #f))))
(set-Node-terminal! head #t))
root)
(define (find upper-bound prefix)
(let/cc return
(define head (generate-trie (calc (Sieve upper-bound #f))))
(define str-prefix (number->string prefix))
(for ([ch (in-string str-prefix)])
(set! head (hash-ref! (Node-children head) ch #f))
(when (not head)
(return #f)))
(define queue (make-queue))
(enqueue! queue (cons head str-prefix))
(let loop ([queue queue]
[result '()])
(cond
[(queue-empty? queue) (sort result <)]
[else
(define top-prefix (dequeue! queue))
(define-values (top prefix) (values (car top-prefix) (cdr top-prefix)))
(for ([(ch v) (in-hash (Node-children top))])
(enqueue! queue (cons v (string-append prefix (string ch)))))
(if (Node-terminal top)
(loop queue (cons (string->number prefix) result))
(loop queue result))]))))
(define (verify)
(define left '(2 23 29))
(define right (find 100 2))
(when (not (equal? left right))
(error 'verify "~s != ~s" left right)))
(define (notify msg)
(with-handlers ([exn:fail:network? void])
(let-values ([(in out) (tcp-connect "localhost" 9001)])
(display msg out)
(close-input-port in)
(close-output-port out))))
(define UPPER-BOUND 5000000)
(define PREFIX 32338)
(module+ test
(verify))
(module+ main
(verify)
(notify (format "Racket\t~s" (getpid)))
(define results (find UPPER-BOUND PREFIX))
(notify "stop")
(displayln results))