My answer to Project Euler problem 4 (largest palindrome of product of two 3-digit numbers) is below.
Please suggest improvements, style changes, indentation, commenting, naming, ...

And nitpicks are welcome!

Other than general stuff about the code below, I'd like to ask specifically about

  1. assert is good to use? Frowned upon? Has possible drawbacks?
  2. progn looks like a 2nd class construct. Is the usage in the final function correct? Are there other (more Lispy-like) options?
(defun e004-digits (n &optional (base 10))
    "return a list with the digits of n"
    (assert (and (integerp n) (>= n 1)
                 (integerp base) (>= base 2)))
    (loop with remainder
          while (> n 0)
          do (setf (values n remainder) (floor n base))
          collect remainder))

(defun e004-palindrome6p (n6)
    "determine if the 6-digit number n6 is a palindrome (in base 10)"
    (assert (and (integerp n6) (>= n6 100000) (<= n6 999999)))
    (let ((dd (e004-digits n6)))
         (and (= (nth 2 dd) (nth 3 dd))
              (= (nth 1 dd) (nth 4 dd))
              (= (nth 0 dd) (nth 5 dd)))))

(defun e004-largest-palindrome-in-square (siz)
    "find maximum palindrome product"
    (do* ((a siz)
          (b siz)
          (sum (+ siz siz))
          (p (* a b) (* a b)))
         ((e004-palindrome6p p) p)
       ;; following half diagonals ensures (proof needed?)
       ;; the first palindrome product found is the largest
       (setf a (+ a 1))
       (setf b (- b 1))
       (if (> a siz) ; start next diagonal
           (progn (setf (values a nextb) (floor sum 2))
                  (setf b (+ a nextb -1))
                  (setf sum (- sum 1))))))

(defun e004 ()
    (e004-largest-palindrome-in-square 999))

code also available on github

  • \$\begingroup\$ progn usage in last function is correct and needed as if's then clause must be a single expression. Note however that setf can take multiple pairs of places and values like (setf x y a b) so you could do that instead of using progn \$\endgroup\$
    – verdammelt
    Jul 5, 2020 at 18:05
  • 1
    \$\begingroup\$ I'd personally consider changing the (if <condition> (progn ...)) to (when <condition> ...). It feels as if it flows a bit better. \$\endgroup\$
    – Vatine
    Nov 4, 2020 at 7:37


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.