2013-01-06 122 views
0

我在嘗試項目euler問題以學習常見的lisp,並且我很早就卡住了。在問題1中,問題是從1到1000的整數總和。我認爲下面的代碼應該這樣做,但它總是返回值end(如果它是mod 3或mod 5)或0代替。返回錯誤值的Common Lisp函數

(defun mod3or5 (n)                 
    (cond                    
    ((equal (mod n 5) 0) n)               
    ((equal (mod n 3) 0) n)               
    (0))))                   

(defun mod-sum (start end)               
    (cond                    
    ((equal start end) (mod3or5 start))            
    (+ (mod3or5 start) (mod-sum (+ start 1) end)))) 

例如

(mod-sum 1 9) 
=> 9 
(mod-sum 1 8) 
=> 0 

我希望答案是23和14分別。

回答

5

給予cond的每個表格的格式爲(condition exp1 ... expn)。如果condition爲真,則它將評估所有表達式並返回expn的值。如果condition爲假,它將繼續下一個表格。

您的最後一張表格是:(+ (mod3or5 start) (mod-sum (+ start 1) end))。因此,這裏+是條件(這將永遠是正確的,因爲+是一個函數,因此不nil),(mod3or5 start)是第一個表達式(將進行評估,但不退還),並(mod-sum (+ start 1) end)是最後一個表達式(將進行評估,並然後返回)。

cond中的「其他分支」是通過選擇t作爲條件來實現的。所以,你的最後形式應該是這樣的:

(t (+ (mod3or5 start) (mod-sum (+ start 1) end))) 
+0

而在mod3or5中0意外返回(如果沒有值子句,則返回測試值並且0非零,所以爲真)。 – Vatine

0

之前我張貼了這個,但它是在計劃,所以我決定把它改寫在一個位,使用loop一變:

(defun euler-1() 
    (loop with x = (list 3 2 1 3 1 2 3) 
    for i in (nconc x x) 
    while (< (+ steps i) 1000) 
    summing i into steps 
    summing steps into result 
    finally (return result))) 

這就是你如何做到這一點,避免模數(因爲它昂貴)。你也會平均步驟2號碼(跳過那些你不需要添加的號碼)。