Common lisp LISP中两个位向量之间的距离
我在使用common lisp计算两个位向量之间的距离时遇到问题 我对lisp很陌生,这是我的人工智能作业的最后一道作业题,我相信我遇到的问题是语法问题 问题是: 在两个位向量之间写一个递归函数距离 由1和0的列表表示的相同长度。对于 例如 (距离"1011"(01101)) 答复:3 讨论如果向量是一个 不同的长度 根据我的理解,两个位向量之间的距离只是将两个位向量进行异或运算,然后计算出1 使用这个例子,我们将得到1011^0101=1110,这将等于3 假设这是计算距离的正确方法,那么我的问题是找到一种在lisp中实现XOR的方法,并使其递归 如何将两个列表转换成一种格式,我可以使用类似于Common lisp LISP中两个位向量之间的距离,common-lisp,bitvector,Common Lisp,Bitvector,我在使用common lisp计算两个位向量之间的距离时遇到问题 我对lisp很陌生,这是我的人工智能作业的最后一道作业题,我相信我遇到的问题是语法问题 问题是: 在两个位向量之间写一个递归函数距离 由1和0的列表表示的相同长度。对于 例如 (距离"1011"(01101)) 答复:3 讨论如果向量是一个 不同的长度 根据我的理解,两个位向量之间的距离只是将两个位向量进行异或运算,然后计算出1 使用这个例子,我们将得到1011^0101=1110,这将等于3 假设这是计算距离的正确方法,那么我的
logxor
的东西,然后计算结果列表中的1
当尝试执行(logxor'(1 0 1 1)'(0 1 0 1))
时,它告诉我'(1 0 1 1)不是整数,因此logxor
似乎无法处理让我不知所措的列表
如果您能提供任何帮助,我们将不胜感激
谢谢 只需将
logxor
映射到您的列表:
? (mapcar #'logxor '(1 0 1 1) '(0 1 0 1))
(1 1 1 0)
数一数:
? (count 1 (mapcar #'logxor '(1 0 1 1) '(0 1 0 1)))
3
或者把所有的东西加在一起:
? (apply #'+ (mapcar #'logxor '(1 0 1 1) '(0 1 0 1)))
3
现在您只需要将其转换为递归
(defun distance (lst1 lst2)
(if (or (null lst1) (null lst2))
0
(+ (logxor (car lst1) (car lst2))
(distance (cdr lst1) (cdr lst2)))))
或尾部递归版本:
(defun distance (lst1 lst2 &optional (res 0))
(if (or (null lst1) (null lst2))
res
(distance (cdr lst1)
(cdr lst2)
(+ res (logxor (car lst1) (car lst2)))))))
然后
LOGXOR处理数字:
CL-USER 43 > (logxor 2 1)
3
还有一种表示法可以将数字写成0和1
CL-USER 44 > (logxor #b1010 #b0101)
15
另见:
CL-USER 45 > (logcount (logxor #b1011 #b0101))
3
如果您想使用一个简单的defun语句,您可以执行以下操作
(defun distance (a b)
(cond
((equal nil a) 0)
(t (+ (rem (+ (first a) (first b)) 2) (distance (rest a) (rest b))))
)
)
简单递归版本不是尾部递归:
(defun distance (v u)
(cond ((null v) (length u)) ; assume that missing is different from both 0 & 1
((null u) (length v)) ; ditto
(t (+ (if (= (first u) (first v)) 0 1)
(distance (rest v) (rest u))))))
这与距离(差异数量)的公理定义相对应,如下所示:
dist(v1,u1)+dist(v2,u2)=dist(v1+v2,u1+u2)
如果length(v1)=length(u1)
<代码>+表示串联length(v1)=length(v2)=1
,则dist(v1,v2):=(v1==v2?0:1)
\*…
表示法可以轻松编写位向量)以及列表。使用mapcar
,您无法获得这种灵活性,它只适用于列表。还要注意使用(reduce'+…)
而不是(apply'+…)
。这有两个原因
reduce
适用于任意序列,因此您可以将其用于向量和列表apply
取决于可传递给函数的最大参数数。虽然这里的小例子不会与之冲突,但是如果你有更大的位向量,你可能会遇到这个问题(logcount(logxor…)
:
太好了,非常感谢。我没有想到使用
car
和cdr
,这使它变得更简单,让我自然地使用logxor
请注意,此解决方案适用于位列表(这是OPs问题所显示的),但不适用于<代码>映射仍然适用于位向量,因为它们是序列。(减少“+…)
也比(应用“+…)
更好,因为应用
会受到影响,这可能是较大向量的问题。答案是肯定的还是否定的3?我不知道你所说的“答案-3”是什么意思。还要注意的是,你正在处理比特列表;Common Lisp实际上有,它通常比位列表更有效。这比它需要的更复杂,而且它不适用于位向量(尽管它适用于位列表,这是问题中实际显示的)。我认为这是我对这个问题的主要混淆点。使用她提供的语法,我找不到任何关于位向量的信息。
(defun distance (v u)
(cond ((null v) (length u)) ; assume that missing is different from both 0 & 1
((null u) (length v)) ; ditto
(t (+ (if (= (first u) (first v)) 0 1)
(distance (rest v) (rest u))))))
(defun distance (bits1 bits2)
(reduce '+ (map 'bit-vector 'logxor bits1 bits2)))
CL-USER> (distance #*1011 #*0101)
3
CL-USER> (distance '(1 0 1 1) '(0 1 0 1))
3
CL-USER> (distance #*1011 '(0 1 0 1))
3
(defun distance (bits1 bits2)
(flet ((to-int (bits)
(if (integerp bits) bits
(reduce (lambda (int bit)
(logior (ash int 1) bit))
bits))))
(logcount (logxor (to-int bits1) (to-int bits2)))))
CL-USER> (distance #b1011 '(0 1 0 1))
3
CL-USER> (distance #*1011 '(0 1 0 1))
3
CL-USER> (distance #*1011 5)
3
CL-USER> (distance 11 5)
3