【问题标题】:Common Lisp Loop Trouble常见的 Lisp 循环问题
【发布时间】:2013-05-11 11:26:19
【问题描述】:

我很难完全理解 CL 的 Loop 宏。 这是我的 Project Euler Nr 的代码。 32:

(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”。它不是只收集泛数字,而是返回一个包含“NIL”和少数正确数字的列表。

如何更改此函数以仅返回我感兴趣的数字?

【问题讨论】:

    标签: lisp common-lisp


    【解决方案1】:

    问题是内部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))
    

    【讨论】:

    • 这可以写得稍微短一点:(loop for i from i to 2000 when (loop ...) collect it)it 是一个预定义的变量,用于保存测试结果。
    • @Rainer Joswig。谢谢。我忘记了循环的照应可能性。