Search code examples
common-lispcollatz

translate list comprehension into Common Lisp loop


I have very recently started learning lisp. Like many others, I am trying my hand at Project Euler problems, however I am a bit stuck at Problem 14 : Longest Collatz Sequence.

This is what I have so far:

(defun collatz (x)
  (if (evenp x) 
      (/ x 2)
      (+ (* x 3) 1)))

(defun collatz-sequence (x)
  (let ((count 1))
    (loop
     (setq x (collatz x))
       (incf count)
       (when (= x 1)
     (return count)))))

(defun result ()
  (loop for i from 1 to 1000000 maximize (collatz-sequence i)))

This will correctly print the longest sequence (525) but not the number producing the longest sequence.

What I want is

result = maximum  [ (collatz-sequence n, n) | n <- [1..999999]]

translated into Common Lisp if possible.


Solution

  • The LOOP variant is not that pretty:

    (defun collatz-sequence (x)
      (1+ (loop for x1 = (collatz x) then (collatz x1)
                count 1
                until (= x1 1))))
    
    (defun result ()
      (loop with max-i = 0 and max-x = 0
            for i from 1 to 1000000
            for x = (collatz-sequence i)
            when (> x max-x)
            do (setf max-i i max-x x)
            finally (return (values max-i max-x))))