List 使用递归时,如何将多个对追加或连接到一个较长的列表中?

List 使用递归时,如何将多个对追加或连接到一个较长的列表中?,list,recursion,scheme,List,Recursion,Scheme,这是一个家庭作业问题,所以请指出一个好的方向,不要给出解决方案。 基本上,在这个方案中,我试图构建一个从逻辑门开始的多位加法器 谢谢你的阅读/帮助 我正在运行的一个示例是使用1进位添加101001和011101。 我觉得我有一个清单,并且一直在追加?但如果这是正确的步骤,我就无法让它工作 (define l-and (lambda (x y) (if (and (equal? x 1) (equal? y 1)) 1 0))) (define l-or (lambda (x y) (if (o

这是一个家庭作业问题,所以请指出一个好的方向,不要给出解决方案。 基本上,在这个方案中,我试图构建一个从逻辑门开始的多位加法器

谢谢你的阅读/帮助

我正在运行的一个示例是使用1进位添加101001和011101。
我觉得我有一个清单,并且一直在追加?但如果这是正确的步骤,我就无法让它工作

(define l-and (lambda (x y) (if (and (equal? x 1) (equal? y 1)) 1 0)))

(define l-or (lambda (x y) (if (or (equal? x 1) (equal? y 1)) 1 0)))

(define l-xor (lambda (x y) (if (or (equal? (l-and x y) 1) (and (equal? x 0) (equal? y 0)) ) 0 1)))

(define l-not (lambda (x) (if (equal? x 0) 1 0)))

(define fulladdr (lambda (x y z)
  (cons
  (l-xor (l-xor x y) z)
  (l-or (l-and x y) (l-and z (l-xor x y)))
  )
))

(define (removelast lis)
  ;(display (reverse(cdr (reverse lis)))) For debugging
  (if (null? (cdr lis)) 
  '() 
  (reverse(cdr (reverse lis)
))))

(define (last-element lis)
  ;(display (car(reverse lis))) For debugging
  (if (null? (cdr lis)) 
  '() (car(reverse lis))
))

(define n-bit-addr (lambda (l1 l2 x) 
  (if (or (null? l1) (null? l2)) 
  '() 
  (let ((carry (cdr (fulladdr (last-element l1) (last-element l2) x)))) 
  (let (( sum (car (fulladdr (last-element l1) (last-element l2) x))))
  ;(display carry) For debugging
  (cons
    (fulladdr (last-element l1) (last-element l2) x)
      (n-bit-addr (removelast l1) (removelast l2) carry)

)))))
当我用这个例子运行代码时,我得到了正确的输出,比如:((1.1)(1.0)(1.0)(0.1)(0.1)(0.1))
我正试图找出如何格式化它,这样我的输出将是(111000.1)。基本上(二进制。最终版本)

以下是一些观察结果。加法器使用进位,所以需要对最低有效位到最高有效位进行运算

列表是从头到尾创建的。例如,可以创建
(12)
(cons1(cons2’()),这意味着需要完成第二个参数
(cons2’())

我猜您的参数是列表中的二进制数字,如
(10 1 0)
as
10
。如果您有一个helper或一个名为
let
的函数,那么到目前为止,您可以使用这两个参数,即进位和求和作为参数,以便将它们用作状态。您还使用相同的参数调用了
fulladdr
,共调用了3次。以下是我认为你应该做的:

(define (n-bit-addr l1 l2)
  (helper (reverse l1) (reverse l2) 0 '())) 
这违背了获取和删除“最后”元素的目的,而不是获取和删除第一个元素,这在Scheme中要容易得多

剩下的就在这里。我已经抽象出了一些挑战,例如,当你做
(n-bit-addr'(1 1 1 0))
时会发生什么,通过不直接使用
car
cdr
可以神奇地解决

(define (helper l1 l2 carry acc)
  ;; actual implementation of n-bit-addr
  (if (finished? l1 l2)
      (finish acc carry)
      (let* ((res (fulladdr (car0 l1) (car0 l2) carry))
             (sum (car res))
             (carry (cdr res)))
        (helper (cdr* l1) <??> <??> <??>))))

(define (car0 lst)
  ;; returns 0 if lst is null? (car lst) otherwise
  )

(define (cdr* lst)
  ;; return '() if lst is null? (cdr lst) otherwise
  )

(define (finished? l1 l2)
  ;; return #t is both are null?
  )

(define (finish sum carry)
  ;; return whatever structure one would want with the last result
  ;; I would imagine carry could be the the highest bit if it's set. thus
  ;; (n-bit-addr '(1) '(1)) ; ==> (1 0)
  )
请注意,
#b1010
只是一种奇特的书写方式
10

(number->logic 10) ; ==> (1 0 1 0)
另一种方法是从0开始累加器,并为列表中的每个元素将累加器乘以2,然后将位相加。当列表为
null?
时,累加器将是数字

(logic->number '(1 0 1 0)) ; ==> 10
我记得在学校用与非门构建加法器,但我在编程方面没有这样做过。你应该试试看

(logic->number '(1 0 1 0)) ; ==> 10