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