p069.scm 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. ;; Totient maximum
  2. (define-module (solved p069))
  3. (use-modules (srfi srfi-1)
  4. (euler primes)
  5. (euler utils))
  6. ;;; So this proc gives the answer really quickly, but not sure if provable
  7. (define-public (max-n/totient-fast n)
  8. (let lp ([primes (erato n)] [acc 1])
  9. (cond
  10. [(null? primes) acc]
  11. [(> (* acc (car primes)) n) acc]
  12. [else
  13. (lp (cdr primes) (* acc (car primes)))])))
  14. (define (max-n/totient n)
  15. (fold (lambda (i totient curr-max)
  16. (let* ([n/totient (/ i totient)])
  17. (if (> n/totient (cdr curr-max))
  18. (cons i n/totient)
  19. curr-max)))
  20. (cons 0 0)
  21. (iota n 2)
  22. (totient-in-range n)))
  23. ;;; The actual fast way to generate totient numbers...
  24. (define (totients-in-range range)
  25. (define primes (erato range))
  26. (define (totient n)
  27. (let lp ([curr-primes primes] [acc n])
  28. (cond
  29. [(null? curr-primes) acc]
  30. [(> (car curr-primes) n) acc]
  31. [else
  32. (lp (cdr curr-primes)
  33. (if (zero? (modulo n (car curr-primes)))
  34. (* acc (- 1 (/ 1 (car curr-primes))))
  35. acc))])))
  36. (let lp ([i 1] [acc '()])
  37. (if (> i range) (drop (reverse acc) 1)
  38. (lp (1+ i)
  39. (cons (totient i) acc)))))
  40. ;;; All the proc below are old attempts
  41. ;; Attempting the speed mod
  42. ;;; This is cool, but not sure if I gained any speed, it uses much less memory however
  43. (define (relative-primes-range-tt limit)
  44. (define non-rel-prime-acc (make-vector (1+ limit) '(0 ())))
  45. (define (update-acc-lp offset i)
  46. (do [(curr-i (+ i offset) (+ curr-i offset))]
  47. [(> curr-i limit)]
  48. (let [(curr-val
  49. (vector-ref non-rel-prime-acc curr-i))]
  50. (vector-set! non-rel-prime-acc
  51. curr-i
  52. (list (1+ (car curr-val))
  53. (if (truth-fold (lambda (val) (= 1 (gcd val i)))
  54. (cadr curr-val))
  55. ;; Appending since we want small values in front
  56. (append (cadr curr-val) (list i))
  57. (cadr curr-val)))))))
  58. (do [(i 2 (1+ i))]
  59. [(> i limit) non-rel-prime-acc]
  60. (when (zero? (modulo i 100)) (display i) (newline))
  61. (let* ([cached-non-rel-primes (cadr (array-ref non-rel-prime-acc i))]
  62. [non-rel-primes (if (null? cached-non-rel-primes) (list i)
  63. cached-non-rel-primes)])
  64. (for-each
  65. (lambda (index)
  66. (update-acc-lp index i))
  67. non-rel-primes))
  68. (vector-set! non-rel-prime-acc
  69. i
  70. (car (vector-ref non-rel-prime-acc
  71. i)))))
  72. ;; This is the faster version that uses more memory
  73. (define (relative-primes-range limit)
  74. (define non-rel-prime-acc (make-vector (1+ limit) '()))
  75. (define (update-acc-lp offset i)
  76. (do [(curr-i (+ i offset) (+ curr-i i))]
  77. [(> curr-i limit)]
  78. (let [(curr-i-non-rel-primes
  79. (vector-ref non-rel-prime-acc curr-i))]
  80. (unless (and (not (null? curr-i-non-rel-primes))
  81. (= i (car curr-i-non-rel-primes)))
  82. (vector-set! non-rel-prime-acc
  83. curr-i
  84. (cons i (vector-ref non-rel-prime-acc curr-i)))))))
  85. (do [(i 2 (1+ i))]
  86. [(> i limit) non-rel-prime-acc]
  87. (when (zero? (modulo i 100)) (display i) (newline))
  88. (let ([i-non-rel-primes (cons i (array-ref non-rel-prime-acc i))])
  89. (for-each
  90. (lambda (index)
  91. (update-acc-lp index i))
  92. i-non-rel-primes)
  93. (vector-set! non-rel-prime-acc
  94. i
  95. (length (vector-ref non-rel-prime-acc
  96. i))))))
  97. (define (get-relative-primes n)
  98. (let loop ((i 1) (acc '()))
  99. (if (> i n) acc
  100. (loop (1+ i)
  101. (if (= 1 (gcd n i))
  102. (cons i acc)
  103. acc)))))
  104. (define (n/totient n)
  105. (/ n (totient n)))
  106. (define (max-n/totient-slow n)
  107. (fold (lambda (n n/totient curr-max)
  108. (if (> n/totient (cadr curr-max))
  109. (list n n/totient)
  110. curr-max))
  111. '(0 0)
  112. (iota (- n 2) 2)
  113. (map n/totient (iota (- n 2) 2))))
  114. (define (max-n/totient-fast n best)
  115. (let loop ((i n) (curr-max (list 0 best)))
  116. (if (<= i 0) curr-max
  117. (loop (1- i) (update-curr-max curr-max i)))))
  118. (define (update-curr-max curr-max n)
  119. (let loop ((i 2) (co-primes 1))
  120. (cond
  121. ((< (/ n co-primes) (cadr curr-max)) curr-max)
  122. ((>= i n) (display (list n (exact->inexact( / n co-primes)))) (newline) (list n (/ n co-primes)))
  123. (else (loop (1+ i)
  124. (if (= 1 (gcd n i))
  125. (1+ co-primes)
  126. co-primes))))))
  127. (define (generate-co-prime-list n)
  128. (define co-prime-vector (make-vector (1+ n) 0))
  129. (define (co-prime-recur node)
  130. (if (> (car node) n) #f
  131. (begin
  132. (let ((m (car node)) (n (cadr node)))
  133. (update-vector node)
  134. (co-prime-recur (list (- (* 2 m) n) m))
  135. (co-prime-recur (list (+ (* 2 m) n) m))
  136. (co-prime-recur (list (+ m (* 2 n)) n))))))
  137. (define (co-prime-iter nodes)
  138. (cond
  139. ((null? nodes) #f)
  140. ((> (car (car nodes)) n) (co-prime-iter (cdr nodes)))
  141. (else (begin
  142. (update-vector (car nodes))
  143. (co-prime-iter
  144. (append (get-children (car nodes))
  145. (cdr nodes)))))))
  146. (define (co-prime-generator nodes)
  147. (display (length nodes))
  148. (newline)
  149. (if (null? nodes) #f
  150. (co-prime-generator (node-loop nodes))))
  151. (define (node-loop nodes)
  152. (append-map
  153. (lambda (node)
  154. (if (> (car node) n) '()
  155. (begin
  156. (update-vector node)
  157. (get-children node))))
  158. nodes))
  159. (define (update-vector node)
  160. (vector-set! co-prime-vector
  161. (car node)
  162. (1+ (vector-ref co-prime-vector
  163. (car node)))))
  164. (begin
  165. (co-prime-iter '((2 1) (3 1)))
  166. (drop (array->list co-prime-vector) 2)))
  167. (define (generate-co-prime-list-1 n)
  168. (define co-prime-vector (make-vector (1+ n) 0))
  169. (define (co-prime-iter nodes i)
  170. (cond
  171. ((null? nodes) #f)
  172. ((> (caar nodes) n) (when (zero? (modulo i 1000000)) (display (length nodes)) (newline)) (co-prime-iter (cdr nodes) (1+ i)))
  173. (else (begin
  174. (update-vector (car nodes))
  175. (co-prime-iter
  176. (append (get-children (car nodes))
  177. (cdr nodes))
  178. i)))))
  179. (define (update-vector node)
  180. (vector-set! co-prime-vector
  181. (car node)
  182. (1+ (vector-ref co-prime-vector
  183. (car node)))))
  184. (begin
  185. (co-prime-iter '((2 1) (3 1)) 0)
  186. (drop (array->list co-prime-vector) 2)))
  187. ;; consider doing a single do?
  188. (define (generate-co-prime-list-sieve n)
  189. (let ([sieve (make-vector (1+ n) 0)])
  190. (do ([i 1 (1+ i)])
  191. ([> i n])
  192. (do ([j (* 2 i) (+ i j)])
  193. ([> j n])
  194. (vector-set! sieve j
  195. (1+ (vector-ref sieve j)))))
  196. (drop (map - (iota (vector-length sieve)) (vector->list sieve)) 2)))
  197. (define (get-children node)
  198. (let ((m (car node)) (n (cadr node)))
  199. (list
  200. (list (- (* 2 m) n) m)
  201. (list (+ (* 2 m) n) m)
  202. (list (+ m (* 2 n)) n))))
  203. (define (get-n/totient n co-primes)
  204. (/ n (totient co-primes)))