【问题标题】:translate list comprehension into Common Lisp loop将列表理解转换为 Common Lisp 循环
【发布时间】:2013-04-27 11:34:13
【问题描述】:

我最近开始学习 lisp。像许多其他人一样,我正在尝试解决 Project Euler 问题,但是我有点卡在Problem 14:最长的 Collat​​z 序列。

这是我目前所拥有的:

(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)))

这将正确打印最长序列 (525),但不会正确打印产生最长序列的数字。

我想要的是

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

如果可能的话,翻译成 Common Lisp。

【问题讨论】:

标签: common-lisp collatz


【解决方案1】:

借助宏的帮助和使用iterate 库,它允许您扩展其loop-like 宏,您可以执行以下操作:

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

(defun collatz-path (x)
  (1+ (iter:iter (iter:counting (setq x (collatz x))) (iter:until (= x 1)))))

(defmacro maximizing-for (maximized-expression into (cause result))
  (assert (eq 'into into) (into) "~S must be a symbol" into)
  `(progn
     (iter:with ,result = 0)
     (iter:reducing ,maximized-expression by
      (lambda (so-far candidate)
        (if (> candidate so-far)
            (progn (setf ,result i) candidate) so-far)) into ,cause)))

(defun euler-14 ()
  (iter:iter
    (iter:for i from 1000000 downto 1)
    (maximizing-for (collatz-path i) into (path result))
    (iter:finally (return (values result path)))))

(提出时不主张一般性。:))

【讨论】:

    【解决方案2】:

    LOOP 变体并不那么漂亮

    (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))))
    

    【讨论】:

      【解决方案3】:

      一个迟到但“漂亮”的答案,虽然输了:

      (defun collatz-sequence (x)
        (labels ((collatz (x)
                   (if (evenp x)
                       (/ x 2)
                       (+ (* 3 x) 1))))
          (recurse scan ((i x) (len 1) (peak 1) (seq '(1)))
            (if (= i 1)
                (values len peak (reverse seq))
                (scan (collatz i) (+ len 1) (max i peak) (cons i seq))))))
      
      (defun collatz-check (n)
        (recurse look ((i 1) (li 1) (llen 1))
          (if (> i n)
              (values li llen)
              (multiple-value-bind (len peak seq)
                  (collatz-sequence i)
                (if (> len llen)
                    (look (+ i 1) i  len)
                    (look (+ i 1) li llen))))))
      
      (defmacro recurse (name args &rest body)
        `(labels ((,name ,(mapcar #'car args) ,@body))
           (,name ,@(mapcar #'cadr args))))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-30
        • 2013-05-16
        • 2020-03-29
        • 1970-01-01
        相关资源
        最近更新 更多