2013-04-27 49 views
3

我最近开始学习lisp。像其他许多人一样,我正在努力解决欧拉计划问题,但是我有点卡在Problem 14:最长的Collat​​z序列。将列表理解转换为Common Lisp循环

这是我到目前为止有:

(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的。

+1

'loop'显然不支持“直接”的方式来实现这一目标。 [这篇文章在'comp.lang.lisp'](https://groups.google.com/forum/?fromgroups=#!topic/comp.lang.lisp/LVEKhM6cheg)中有一个手动解决方案。 – 2013-04-27 11:54:47

回答

4

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

与宏一些帮助,并使用iterate库,它允许您扩展其loop般的宏,你可以做类似下面:

(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

逾期答案,但一个“漂亮”之一,虽然丢失的一个:

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

+ 1为递归宏和一个很好的示例用例 – 2013-04-28 21:08:23