To start with Common Lisp I am doing Project Euler using this language. Usually I manage to solve problems but I am quite sure that my code is not as efficient as it could be in Common Lisp. That is why I need a review from experienced lispers.
This is my code for problem 35. Please offer any improvements.
(defun prime-p (n)
(cond
((= n 1) nil)
((= n 2) t)
((evenp n) nil)
(t (loop for i from 3 to (isqrt n) by 2
never (zerop (mod n i))))))
(defun list->num (lst)
(loop for i in lst
for p = (- (length lst) 1) then (- p 1)
sum (* i (expt 10 p))))
(defun num->list (n)
(loop for c across (write-to-string n)
collect (parse-integer (string c))))
(defun rotate (lst)
(append (last lst) (butlast lst)))
(defun number-rotations (n)
(let* ((digits (num->list n))
(digits-count (length digits)))
(loop repeat digits-count
for rotated = digits then (rotate rotated)
collect (list->num rotated))))
(defun problem-35 (limit)
(let ((hash-primes (make-hash-table)))
(loop for n from 1 to limit
if (prime-p n)
do (setf (gethash n hash-primes) t))
(loop for p being the hash-keys in hash-primes
if (loop for n in (number-rotations p)
always (gethash n hash-primes))
collect p)))
3 Answers 3
In list->num
you can count down with something like for i downfrom n
.
(defun num->list (n)
(loop for c across (write-to-string n)
collect (parse-integer (string c))))
In above function you can just collect (digit-char-p c)
. The function returns the digit value as a number.
Consider giving common lisp some optimizing hints. Adding a single (declare (fixnum n)
takes the runtime (on my machine) of (euler-35 1000000)
from 1.2 seconds to 0.83 seconds:
(defun prime-p (n)
(declare (fixnum n))
(cond
((= n 1) nil)
((= n 2) t)
((evenp n) nil)
(t (loop for i from 3 to (isqrt n) by 2
never (zerop (mod n i))))))
If you treat primes below 1,000,000, memorize primes below 1,000. Use strings in rotation operation.
(defun print-rotation (number)
(let* ((str (format nil "~a" number))
(strstr (concatenate 'string str str)))
(loop for i below (length str) do
(format t "~a~%" (parse-integer (subseq strstr i (+ i (length str))))))))
Explore related questions
See similar questions with these tags.