我需要创建一个LISP函数,给定一个整数列表(x_1 x_2 ... x_n)
,计算元素之间所有差异的乘积,
Π (x_i - x_j), where i < j
例如,对于列表:(4 3 2)
,函数应计算:(4-2)(4-3)(3-2) = 2
。如果列表为空,函数应该返回1
。
这是我尝试过的:
对于空列表:
(defun dprod0 (lst)
(if (null lst)
1))
For list with 1:
(defun dprod1 (lst)
(if (= (list-length lst) 1)
1))
这是我目前看到的
(defun dprod (lst)
(cond
((null lst) 1)
((= (list-length lst) 1) 1)
(t (let ((a (first lst))
(b (second lst))
(r (cdr lst)))
(* (- a b) (dprod r))))))
如果我们只需要知道它是空的((null lst)
)还是只包含一个元素((null (cdr lst))
),那么通常我们尽量不要不必要地测量整个列表的lst
长度。因此你的代码变成了
(defun dprod (lst)
(cond
((null lst) 1)
((null (cdr lst)) 1)
(t (let ((a (first lst))
(b (second lst))
(r (cdr lst)))
(* (- a b)
(dprod r))))))
这是一个完美的代码,但它计算什么呢?我们将潦草地写一些例子来看看是怎么回事。我们将使用{...}
来指示转换:
{ [ ] } ==> 1
{ [ 2 ] } ==> 1
{ [ 3, 2 ] } ==> (* (- 3 2) { [2] } ) ==> (3-2)*1
到目前为止一切顺利。接下来,
{ [ 4, 3, 2 ] } ==> (* (- 4 3) { [3,2] } ) ==> (4-3)*(3-2)*1
,这是错误的。我们需要(4-2)*(4-3)*(3-2)*1
。这与(4-3)*(4-2)*(3-2)*1
相同。
这意味着在形成差异(4-3
,3-2
)时,我们只将第一个元素4
与后面的元素3
配对。但我们也需要把它和其他的配对起来。你的代码是这样做的:
{ [ 5, 4, 3, 2 ] } ==> (5-4)*(4-3)*(3-2)*1
但是它必须这样做:
{ [ 5, 4, 3, 2 ] } ==> (5-4)*(5-3)*(5-2)*
(4-3)*(4-2)*
(3-2)*
1
因此我们必须将其扩充为
(defun dprod (lst)
(cond
((null lst) 1)
((null (cdr lst)) 1)
(t (let ((a (first lst))
(b (second lst))
(r (cdr lst)))
(* (diffs a r) ;; NB <<<----------
(dprod r))))))
以便计算
{ [ 5, 4, 3, 2 ] } ==> (5-4)*(5-3)*(5-2)* == (diffs 5 [4,3,2])*
(4-3)*(4-2)* == (diffs 4 [3,2])*
(3-2)* == (diffs 3 [2])*
1 == (dprod [2])
现在您需要编写这个diffs
函数。
之后,您还可以简化dprod
的代码。