faster factor, (factor 1) = () (issue #751 cont.)

no need to go up to sqrt(n), Instead track i^2 and quit when that gets
larger than the (remaining) n (i.e., not the original n)
This commit is contained in:
Roger Crew 2021-06-27 03:58:58 -07:00
parent 41aa1a918e
commit b89bd9f889
2 changed files with 20 additions and 25 deletions

View file

@ -71,7 +71,7 @@
(test #t (perfect? 496)) (test #t (perfect? 496))
(test #t (perfect? 8128)) (test #t (perfect? 8128))
(test '(1) (factor 1)) (test '() (factor 1))
(test '(2) (factor 2)) (test '(2) (factor 2))
(test '(3) (factor 3)) (test '(3) (factor 3))
(test '(2 2) (factor 4)) (test '(2 2) (factor 4))
@ -86,6 +86,7 @@
(test '(2 3 3) (factor 18)) (test '(2 3 3) (factor 18))
(test '(2 2 2 3 3) (factor 72)) (test '(2 2 2 3 3) (factor 72))
(test '(3 3 3 5 7) (factor 945)) (test '(3 3 3 5 7) (factor 945))
(test-error (factor 0))
(test 975 (aliquot 945)) (test 975 (aliquot 945))

View file

@ -192,30 +192,24 @@
;;> Returns the factorization of \var{n} as a monotonically ;;> Returns the factorization of \var{n} as a monotonically
;;> increasing list of primes. ;;> increasing list of primes.
(define (factor n) (define (factor n)
(cond (when (zero? n)
((negative? n) (error "cannot factor 0"))
(cons -1 (factor (- n)))) (factor-twos
((<= n 2) n
(list n)) (lambda (b n)
(else (let lp ((i 3) (ii 9) (n (abs n))
(let lp ((n n) (res (append (make-list b 2)
(res (list))) (if (negative? n) (list -1) '()))))
(cond (cond
((even? n) ((> ii n)
(lp (quotient n 2) (cons 2 res))) (reverse (if (= n 1) res (cons n res))))
((= n 1) ((zero? (remainder n i))
(reverse res)) (lp i ii (quotient n i) (cons i res)))
(else (else
(let lp ((i 3) (n n) (limit (exact (ceiling (sqrt n)))) (res res)) (lp (+ i 2)
(cond (+ ii (* (+ i 1) 4))
((= n 1) n
(reverse res)) res)))))))
((> i limit)
(reverse (cons n res)))
((zero? (remainder n i))
(lp i (quotient n i) limit (cons i res)))
(else
(lp (+ i 2) n limit res))))))))))
;;> Returns the Euler totient function, the number of positive ;;> Returns the Euler totient function, the number of positive
;;> integers less than \var{n} that are relatively prime to \var{n}. ;;> integers less than \var{n} that are relatively prime to \var{n}.