Problem 7, and add a test suite
author |
Steve Losh <steve@stevelosh.com> |
date |
Sun, 10 Apr 2016 14:30:17 +0000 |
parents |
37bd082d9946
|
children |
20c03264a55e
|
branches/tags |
(none) |
files |
Makefile euler.asd euler.lisp package.lisp primes.lisp run-tests.lisp utils.lisp |
Changes
--- a/Makefile Sun Apr 10 01:39:44 2016 +0000
+++ b/Makefile Sun Apr 10 14:30:17 2016 +0000
@@ -1,4 +1,7 @@
-.PHONY:
+.PHONY: test
quickutils.lisp: make-utilities.lisp
sbcl --noinform --load make-utilities.lisp --eval '(quit)'
+
+test:
+ sbcl --noinform --load run-tests.lisp --eval '(quit)'
--- a/euler.asd Sun Apr 10 01:39:44 2016 +0000
+++ b/euler.asd Sun Apr 10 14:30:17 2016 +0000
@@ -9,6 +9,7 @@
:version "0.0.1"
:depends-on (#:defstar
+ #:fiveam
#:optima
#:trivial-types
#:cl-arrows
--- a/euler.lisp Sun Apr 10 01:39:44 2016 +0000
+++ b/euler.lisp Sun Apr 10 14:30:17 2016 +0000
@@ -124,3 +124,20 @@
:sum i))))
(abs (- (sum-of-squares 100) ; apparently it wants the absolute value
(square-of-sum 100)))))
+
+(defun problem-7 ()
+ (nth-prime 10001))
+
+;;;; Tests
+(def-suite :euler)
+(in-suite :euler)
+
+(test p1 (is (= 233168 (problem-1))))
+(test p2 (is (= 4613732 (problem-2))))
+(test p3 (is (= 6857 (problem-3))))
+(test p4 (is (= 906609 (problem-4))))
+(test p5 (is (= 232792560 (problem-5))))
+(test p6 (is (= 25164150 (problem-6))))
+(test p7 (is (= 104743 (problem-7))))
+
+; (run! :euler)
--- a/package.lisp Sun Apr 10 01:39:44 2016 +0000
+++ b/package.lisp Sun Apr 10 14:30:17 2016 +0000
@@ -1,7 +1,9 @@
(defpackage #:euler.utils
(:use #:cl #:euler.quickutils)
(:export
+ #:random-exclusive
#:dividesp))
(defpackage #:euler
- (:use #:cl #:euler.quickutils #:euler.utils))
+ (:use #:cl #:5am
+ #:euler.quickutils #:euler.utils))
--- a/primes.lisp Sun Apr 10 01:39:44 2016 +0000
+++ b/primes.lisp Sun Apr 10 14:30:17 2016 +0000
@@ -16,4 +16,58 @@
(nreverse result)))
+(defun fermat-prime-p (p &optional (tests 10))
+ "Return whether `p` might be prime.
+ Checks `tests` times.
+
+ If `t` is returned, `p` might be prime. If `nil` is returned it is definitely
+ composite.
+
+ "
+ (if (or (zerop p) (= 1 p))
+ nil
+ (flet ((fermat-check (a)
+ (= 1 (mod (expt a (1- p)) p))))
+ (loop :repeat tests
+ :when (not (fermat-check (random-exclusive 0 p)))
+ :do (return nil)
+ :finally (return t)))))
+
+(defun brute-force-prime-p (p)
+ "Return (slowly) whether `p` is prime."
+ (cond
+ ((or (= p 0) (= p 1)) nil)
+ ((= p 2) t)
+ ((evenp p) nil)
+ (t (loop :for divisor :from 3 :to (sqrt p)
+ :when (dividesp p divisor)
+ :do (return nil)
+ :finally (return t)))))
+
+
+(defun primes-below (n)
+ "Return (slowly) the prime numbers less than `n`."
+ (cond
+ ((<= n 2) (list))
+ ((= n 3) (list 2))
+ (t (cons 2 (loop :for i :from 3 :by 2 :below n
+ :when (brute-force-prime-p i)
+ :collect i)))))
+
+(defun primes-upto (n)
+ "Return (slowly) the prime numbers less than or equal to `n`."
+ (primes-below (1+ n)))
+
+
+(defun nth-prime (n)
+ "Return (slowly) the `n`th prime number."
+ (if (= n 1)
+ 2
+ (loop :with seen = 1
+ :for i :from 3 :by 2
+ :when (brute-force-prime-p i)
+ :do (progn
+ (incf seen)
+ (when (= seen n)
+ (return i))))))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/run-tests.lisp Sun Apr 10 14:30:17 2016 +0000
@@ -0,0 +1,15 @@
+(let ((*standard-output* (make-broadcast-stream)))
+ (ql:quickload "euler"))
+
+
+(defvar *passed* t)
+
+(defun test (spec)
+ (let ((result (5am:run spec)))
+ (5am:explain! result)
+ (when (not (5am:results-status result))
+ (setf *passed* nil))))
+
+(test :euler)
+
+(sb-ext:exit :code (if *passed* 0 1))
--- a/utils.lisp Sun Apr 10 01:39:44 2016 +0000
+++ b/utils.lisp Sun Apr 10 14:30:17 2016 +0000
@@ -1,5 +1,9 @@
(in-package #:euler.utils)
+(defun random-exclusive (min max)
+ "Return an integer in the range (`min`, `max`)."
+ (+ 1 min (random (- max min 1))))
+
(defun dividesp (n divisor)
"Return whether `n` is evenly divisible by `divisor`."
(zerop (mod n divisor)))