2013-05-11 149 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