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

时间:2019-04-22 02:54:12

标签: list recursion scheme

这是一个作业问题,因此请指出正确的方向,不要提供解决方案。 基本上,在Scheme中,我试图构建一个从逻辑门开始的多位加法器。

感谢您的阅读/帮助。

我正在运行的示例是将101001和011101随身携带1个。
我觉得我有一份清单,并且会一直附加吗?但是,如果这是正确的步骤,那么我将无法正常工作。

(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)。基本上(二进制。FinalCarry)

1 个答案:

答案 0 :(得分:0)

以下是一些观察结果。加法器使用进位,因此您需要对有效数字进行最高有效的运算。

从头到尾创建一个列表。例如。可以创建(1 2) (cons 1 (cons 2 '())),这意味着第二个参数(cons 2 '())需要完成。

我猜您的参数是(1 0 1 0)10之类的列表中的二进制数字。如果您有一个帮手或一个名为let的人,到目前为止,您可以拥有两个参数,即进位和求和作为参数,以便可以将它们用作状态。同样,您使用相同的参数调用fulladdr 3次。我认为这是您应该做的:

(define (n-bit-addr l1 l2)
  (helper (reverse l1) (reverse l2) 0 '())) 

这违反了获取和删除“最后一个”元素以及获取和删除第一个元素的目的,这在Scheme中更容易实现。

剩下的就在这里。我已经摘录了一些挑战。通过不直接使用(n-bit-addr '(1 1) '(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)
  )

现在,如果(1 0 1 0)不令人满意,您应该制作将number->logic转换为logic->number的{​​{1}}和(1 0 1 0)。这可以通过列表迭代和算术轻松完成。由于您想知道如何对列表进行编号,因此我将采取另一种方式:

#b1010

请注意,(define (number->logic n) (let loop ((n n) (acc '())) (cond ((not (zero? n)) (loop (quotient n 2) (cons (remainder n 2) acc))) ((null? acc) '(0)) (else acc)))) (number->logic #b1010) ; ==> (1 0 1 0) 只是写#b1010的一种奇特方式

10

另一种方法是将累加器从0开始,并针对列表中的每个元素按顺序将累加器乘以2并加该位。如果列表为(number->logic 10) ; ==> (1 0 1 0) ,则累加器为数字。

null?

我记得在学校用nand门构建加法器,但在编程中却没有这样做。你应该试试看。