在Common Lisp中查找嵌套列表的平均值

时间:2014-11-07 17:36:10

标签: lisp common-lisp average nested-lists

我一直在努力达到嵌套列表的平均值,这就是我现在所拥有的:

(defun nested-average2 (tree &optional (sum 0) (count 0))
  (cond ((null tree)
         (/ sum count))
        ((listp (first tree))
         (nested-average2 (rest tree)
                          (nested-average2 (first tree) sum)
                          (incf count)))
        (t
         (nested-average2 (rest tree)
                          (+ sum (first tree))
                          (incf count)))))    

但是它返回非整数

例如,使用此(nested-average2 ' (10 ((30 1) 20) (8 (5 (50 7)) 9) 40)),当它返回18时返回2425/192

2 个答案:

答案 0 :(得分:3)

您的代码适用于普通列表,但不适用于子列表。

  • 其中一个问题是,当您递归到子列表时,只会增加一个的计数,而不是增加已处理的元素数。
  • 另一方面,在这种情况下,您已经计算出了一个“低于平均水平”的平均值。你加入总和。

最简单的方法是计算总和和计数,直到你完成整棵树为止;只有这样你才能进行最后的分工以计算平均值,例如:

(defun nested-average (sxp)
  (labels
      ((sub (sxp tot cnt)
         (cond
          ((null sxp)  (values tot cnt))
          ((consp sxp) (multiple-value-bind (tot1 cnt1) (sub (car sxp) tot cnt)
                         (sub (cdr sxp) tot1 cnt1)))
          (t           (values (+ tot sxp) (1+ cnt))))))
    (multiple-value-bind (tot cnt) (sub sxp 0 0)
      (/ tot cnt))))

答案 1 :(得分:1)

以下类似于Le Petit Prince但没有返回多个值的本地函数。基本上,这会做深度优先行走,并对叶子进行求和和计数。

(defun nested-average2 (tree)
  (let ((sum 0)
        (cnt 0))
    (labels ((leaf-sum-cnt (branch)
               (cond ((null branch))          ; nothing
                     ((listp branch)          ; follow the branches
                      (leaf-sum-cnt (car branch))
                      (leaf-sum-cnt (cdr branch)))
                     (t (incf sum branch)     ; at a leaf
                        (incf cnt)))))
      (leaf-sum-cnt tree)
      (/ sum cnt))))

当然这个例子不是很实用。所以,如果这是家庭作业,你的教授可能不喜欢它。