2013-05-11 135 views
0

我完全理解CL的Loop宏有一些麻煩。 這是我的Project Euler Nr的代碼。 32:Common Lisp Loop Trouble

(defun number-to-list (nr) 
    (map 'list #'digit-char-p (prin1-to-string nr))) 

(defun nine-digits-p (multiplicand multiplier) 
    (= (length (equationlist multiplicand multiplier 
            (* multiplicand multiplier))) 9)) 

(defun equationlist (multiplicand multiplier product) 
    (append (number-to-list multiplicand) (number-to-list multiplier) 
     (number-to-list product))) 

(defun pandigital (multiplicand multiplier) 
    (equal (sort (equationlist multiplicand multiplier 
       (* multiplicand multiplier)) #'<) 
    '(1 2 3 4 5 6 7 8 9))) 

(defun pandigital-list() 
    (loop 
     for i from 1 to 2000 collect 
     (loop for j from 2 to 2000 
     when (and (nine-digits-p i j) (pandigital i j)) collect (* i j)))) 


(defun euler-32() 
    (reduce #'+ (reduce #'union (pandigital-list)))) 

雖然這給了我正確的解決方案,但我的問題是功能「pandigital-list」。它不是隻收集pandigital數字,而是返回一個填充「NIL」和少數正確數字的列表。

如何更改此功能以僅返回我感興趣的數字?

回答

3

問題是,內部的loop返回nil,只要它不收集任何東西。 (記住:在Common Lisp的任何事物都有一個值。)

一種解決方案是重新定義pandigital-list這樣的:

(defun pandigital-list() 
    (loop for i from 1 to 2000 
     for sublist = (loop for j from 2 to 2000 
          when (and (nine-digits-p i j) 
             (pandigital i j)) 
          collect (* i j)) 
      when sublist collect sublist)) 
+4

這可以寫成稍短:'(環路我從我到2000年的時候(環...)收集它)'。它是一個預定義的變量,用來保存測試結果。 – 2013-05-11 18:06:33

+0

@Rainer Joswig。謝謝。我忘了循環的照應可能性。 – 2013-05-11 18:28:53