2013-04-27 81 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