Skip to content

Commit

Permalink
xlisp-23: setup prime-factors exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
wobh committed Sep 30, 2015
1 parent 6cf3d38 commit 1982134
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 1 deletion.
3 changes: 2 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"allergies",
"sieve",
"strain",
"atbash-cipher"
"atbash-cipher",
"prime-factors"
],
"deprecated": [

Expand Down
47 changes: 47 additions & 0 deletions prime-factors/example.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
(defpackage #:prime-factors
(:use #:cl)
(:export #:factors-of)
(:documentation "Generates a list of prime factors of given integer."))

(in-package #:prime-factors)

(defun make-wheel-2-3-5-7 ()
"Returns function generating prime-ish numbers."
(let ((incr '#0=(2 4 2 4 6 2 6 4 2 4 6 6
2 6 4 2 6 4 6 8 4 2 4
2 4 8 6 4 6 2 4 6 2 6
6 4 2 4 6 2 6 4 2 4 2
10 2 10 . #0#))
(next '(2 3 5 7 11))
(last nil))
(lambda ()
(if next
(setf last (pop next))
(incf last (pop incr))))))

(defun factors-of (number)
"List prime factors of `number'.
Based on algorithm A from TAoCP 4.3.4 but with a larger wheel."

This comment has been minimized.

Copy link
@verdammelt

verdammelt Oct 1, 2015

Well damn. You quote TAoCP... anything I say will be wrong. :)

You can always pull out Knuth's quote: "I didn't have time to test it, I only have time to prove it correct".

This comment has been minimized.

Copy link
@wobh

wobh Oct 1, 2015

Author Owner

Not so. Knuth has a bounty for corrections and he has paid for a great many. I have only the second edition and Volume 2 by itself has 130+ pages of errata!

Besides, I'm implementing it, not Knuth. There's probably several improvements.

(declare (type integer number))
(loop
with factors = ()
initially (unless (< 1 number) (loop-finish))
with dividend = number
with next-divisor = (make-wheel-2-3-5-7)
with divisor = (funcall next-divisor)
do
(multiple-value-bind (quotient remainder)
(floor dividend divisor)
(cond ((zerop remainder)
(push divisor factors)
(if (= 1 quotient)
(loop-finish)
(setq dividend quotient)))
((> quotient divisor)
(setq divisor (funcall next-divisor)))
(t
(push dividend factors)
(loop-finish))))
finally
(return (nreverse factors))))
80 changes: 80 additions & 0 deletions prime-factors/prime-factors-test.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
(ql:quickload "lisp-unit")

(defpackage #:prime-factors-test
(:use #:common-lisp #:lisp-unit))

#-xlisp-test (load "prime-factors")

(in-package #:prime-factors-test)

(define-test one
(assert-equal '() (prime-factors:factors-of 1)))

(define-test two
(assert-equal '(2) (prime-factors:factors-of 2)))

(define-test three
(assert-equal '(3) (prime-factors:factors-of 3)))

(define-test four
(assert-equal '(2 2) (prime-factors:factors-of 4)))

(define-test six
(assert-equal '(2 3) (sort (prime-factors:factors-of 6) #'<)))

(define-test eight
(assert-equal '(2 2 2) (prime-factors:factors-of 8)))

(define-test nine
(assert-equal '(3 3) (prime-factors:factors-of 9)))

(define-test twenty-seven
(assert-equal '(3 3 3) (prime-factors:factors-of 27)))

(define-test six-hundred-twenty-five
(assert-equal '(5 5 5 5) (prime-factors:factors-of 625)))

(define-test a-large-number
(assert-equal '(5 17 23 461)
(sort (prime-factors:factors-of 901255) #'<)))

(define-test a-huge-number
(assert-equal '(11 9539 894119)
(sort (prime-factors:factors-of 93819012551) #'<)))

(define-test triple-squares-number
(assert-equal '(2 2 5 5 7 7)
(sort (prime-factors:factors-of 4900) #'<)))

(define-test mersenne-composite-1
(assert-equal '(23 89)
(sort (prime-factors:factors-of 2047) #'<)))

(define-test fermat-composite-1
(assert-equal '(641 6700417)
(sort (prime-factors:factors-of 4294967297) #'<)))

(define-test weak-probable-prime
(assert-equal '(11 31)
(sort (prime-factors:factors-of 341) #'<)))

(define-test strong-probable-prime
(assert-equal '(7 31 73)
(sort (prime-factors:factors-of 15841) #'<)))

(define-test carmichael-small-1
(assert-equal '(3 11 17)
(sort (prime-factors:factors-of 561) #'<)))

(define-test carmichael-small-2
(assert-equal '(11 13 17 31)
(sort (prime-factors:factors-of 75361) #'<)))

(define-test pseudoprime-smallish
(assert-equal '(1303 16927 157543)
(sort (prime-factors:factors-of 3474749660383) #'<)))

#-xlisp-test
(let ((*print-errors* t)
(*print-failures* t))
(run-tests :all :prime-factors-test))

0 comments on commit 1982134

Please sign in to comment.