Common lisp LISP中两个位向量之间的距离

Common lisp LISP中两个位向量之间的距离,common-lisp,bitvector,Common Lisp,Bitvector,我在使用common lisp计算两个位向量之间的距离时遇到问题 我对lisp很陌生,这是我的人工智能作业的最后一道作业题,我相信我遇到的问题是语法问题 问题是: 在两个位向量之间写一个递归函数距离 由1和0的列表表示的相同长度。对于 例如 (距离"1011"(01101)) 答复:3 讨论如果向量是一个 不同的长度 根据我的理解,两个位向量之间的距离只是将两个位向量进行异或运算,然后计算出1 使用这个例子,我们将得到1011^0101=1110,这将等于3 假设这是计算距离的正确方法,那么我的

我在使用common lisp计算两个位向量之间的距离时遇到问题

我对lisp很陌生,这是我的人工智能作业的最后一道作业题,我相信我遇到的问题是语法问题

问题是:

在两个位向量之间写一个递归函数距离 由1和0的列表表示的相同长度。对于 例如

(距离"1011"(01101))

答复:3

讨论如果向量是一个 不同的长度

根据我的理解,两个位向量之间的距离只是将两个位向量进行异或运算,然后计算出1

使用这个例子,我们将得到1011^0101=1110,这将等于3

假设这是计算距离的正确方法,那么我的问题是找到一种在lisp中实现XOR的方法,并使其递归

如何将两个列表转换成一种格式,我可以使用类似于
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)
  • 如果您需要尾部递归版本(编译器可以更容易地将其转换为迭代),则需要将部分结果与函数一起携带。

    您的问题提到了“位向量”,但实际上您正在处理位列表。不过,CommonLisp实际上提供了一个类型。这是一种特殊类型的数组。但它仍然是一个向量,因此您可以使用处理任意序列(向量或列表)的序列函数,因此您可以编写一个解决方案,用于位向量以及元素为位的任何其他序列,方法是:

    它可以按预期工作,但请注意,您可以使用位向量(使用
    \*…
    表示法可以轻松编写位向量)以及列表。使用
    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