球拍捕获功能的结果

Racket Capturing Result of Function

我正在制作一个手动将大数字相加的函数(没有库函数),但我在捕获要显示的结果时遇到了一些问题。我只是简单地向后显示'()。这是它应该如何工作的一些背景知识:如果我通过 (big-add1 '(999) '(456) 0),我应该 return '(455 1)。如果我通过 (big-add1 '(999 234 681) '(456) 0) 我应该 return '(455 235 681)。但到目前为止,我没有成功显示除空列表以外的任何内容。这是我的代码:

(define (big-add1 x y co)
(cond
;; If both lists are empty, the return value is either 0 or the carryover value.
[(and (= 0 (length x)) (= 0 (length y)))
  (if (= co 0) '() (list co))]
[(= 0 (length x))  (big-add1 (list co) y 0)]
[(= 0 (length y))  (big-add1 x (list co) 0)]
[else
 (cond(< (length x) (length y)) (big-add1 y x 0)) ;reverse the order of parameters
 (append (list(+ (modulo (car x) 10) (modulo (car x) 10) co))) ;trying to construct a result
 (if(>(+ (modulo (car x) 10) (modulo (car x) 10) co) 9)
    (letrec ([co 1]) co) ;if addition produces a double digit number set carryover value
    (letrec ([co 0]) co));if addition produces a single digit number
 (if(or(> (car x) 10) (> (car y) 10)) ;we got down to single digits
    (big-add1(append(list(quotient (car x) 10)) (cdr x)) (append(list(quotient (car y) 10)) (cdr y)) co)
    (big-add1 (cdr x) (cdr y) co))
 ]
))

(big-add1 '(999) '(456) 0)
(big-add1 '(999 234 681) '(456) 0)

奖金问题:如果有人愿意,我可以在调试模式下看到当总和大于 10 时 co 没有更改为 1。它似乎执行了该行,但实际上并没有改变它.谁能澄清发生了什么事? 我对此非常陌生,所以如果有人对如何简化它有任何建议,请随时告诉我。我真的很感激。谢谢你的时间。

首先,您的代码中有很多错误。我列出了几个大的:

  • 方案不会 return 除非它是最后一个表达式。 第一个 else 子句的 cond 表达式是典型的不 return.
  • append 不会更改给定列表的内容。是;; trying to...评论部分。不确定你想做什么。
  • letrec 的使用没有任何作用。如果要更改绑定值,请使用 set!.

其次,以下不是错误,只是提示:

  • 您不必创建列表然后 append 来创建列表。只需使用 list。使用 cons 构建列表,然后 reverse 结果是 return 列表的常用成语之一。因此,如果您看到使用 append,请考虑这个。
  • null? 检查空列表的程序。如果你想使用它来检查它而不是将它的长度与 0 进行比较。

最后,下面是符合您要求的。

;; each element must be less than 1000
(define (big-add1 x y co)
  (let loop ((x x) (y y) (co co) (r '()))
    (cond
     ;; If both lists are empty, the return value is either 0
     ;; or the carryover value.
     [(and (null? x) (null? y))
      ;; if there's carry then we need to add it
      (if (zero? co) (reverse r) (reverse (cons co r)))]
     [(null? x) (loop x (cdr y) 0 (cons (+ co (car y)) r))]
     [(null? y) (loop (cdr x) y 0 (cons (+ co (car x)) r))]
     [else
      (let ((r (+ (car x) (car y) co))) ;; add elements
        ;; separate result into element+carry
        ;; NB: it's better not to put magic number.
        (let-values (((e co) (if (> r 1000)
                                 (values (modulo r 1000) 1)
                                 (values r 0))))
          ;; next
          (loop (cdr x) (cdr y) co (cons e r))))])))

你看起来和我在同一个class,所以我也许能帮上点忙。上面的 Takashi Kato 已经回答了你关于 racket/scheme returns 结果如何的问题(只有最后一个表达式会 return 结果)但我想我可以详细说明你的解决方案'正在尝试到达。

正如您在问题中所描述的,big-add 函数有两个参数,这两个参数基本上是 "chunks" 的列表,代表一个数字,例如列表 '(999 456) 被处理为类似于 456,999 的数字。给定列表中的每个 "chunk" 的最大范围只能是 0 到 999(假设我们只是在此处添加正数)。

尽管 Kato 先生的解决方案可能有效,但 Austin 博士(如果我们有相同的教授)更希望您以递归方式完成此问题,并 return 以与传入的参数("chunks" 的列表)。所提供的列表无需反转即可使用。

这是一种思考方式:

  • 当您将 "chunks" 个数字相加时,您 appendcons 每个块的总和创建一个列表 return 您的结果.
  • 如果块的总和超过 999,则意味着它将具有结转值。由于单个块的最大值为 999,因此下一个块中的值 1 等于前一个块中的 1000——这意味着您必须减去(或取模,无论您的偏好如何,因为它们完成相同的任务)1000 以内您当前的块,然后将值 1 传递给下一个计算。
  • 因此,当我们从每个列表中的每个块移动到下一个时,每个块总和将是 x 块、y 块和结转值(如果有的话)的总和。

算法看起来像这样:

  1. 通过将 car xcar yco 相加来计算块总和:(+ (car x) (car y) co)。您可以使用 let 将此值存储到 ID 中。我将我的名称命名为 chunk-sum,但您可以将其命名为任何便于您理解的名称。在我们的 let 正文中,您必须定义如何处理我们的 chunk-sum 以及如何开始创建您 return.
  2. 的列表
  3. 如果 chunk-sum 等于或大于 1000 或 MAX_BLOCK_VALUE(如果您定义了该 ID,它们是等效的),那么会有一个结转值,因此您需要使用 condif.
  4. 使用 appendcons 创建列表。我发现 cons 更适合此解决方案,因为 cons 可以将数字元素作为其第一个参数,其中 append 仅采用列表(因此要求您在 chunk-sum).在此步骤中,您将不得不递归调用函数 big-add1 以不断将元素添加到您的列表中。如果不完全相同,您的递归调用代码将类似于 (big-add1 (cdr x) (cdr y) 0)
  5. 函数将 return 达到基本情况后的值。在这种情况下,我们的基本情况是没有更多的块可以加在一起。

下面是您要尝试完成的代码:

#lang racket

(define MAX_BLOCK_VALUE 1000)

;; Addition of two big-nums
(define (big-add x y)
  (big-add1 x y 0)
  )

(define (big-add1 x y co)
  (cond
    ;; If both lists are empty, the return value is either 0 or the carryover value. This is our base case
    [(and (= 0 (length x)) (= 0 (length y)))
     (if (= co 0) '() (list co))]
    [(= 0 (length x))  (big-add1 (list co) y 0)]
    [(= 0 (length y))  (big-add1 x (list co) 0)]
    [else
     #| code is here |#
     (let ((chunk-sum (+ (car x) (car y) co)))
       (if (>= chunk-sum MAX_BLOCK_VALUE)
           ;; use cons/append and call recursive step for if we have carryover
           (error "foo")
           ;; use cons/append and call recursive step for if we don't have carryover
           (error "bar")
           )
       )
     ]
    ))

希望对您有所帮助。

我可以通过大大简化我的算法来解决这个问题。这是我最终得到的结果:

(define (big-add1 x y co)
(cond
;; If both lists are empty, the return value is either 0 or the carryover value.
[(and (= 0 (length x)) (= 0 (length y)))
  (if (= co 0) '() (list co))]
[(= 0 (length x))  (big-add1 (list co) y 0)]
[(= 0 (length y))  (big-add1 x (list co) 0)]
[else
 (cons(modulo (+ (car x) (car y) co) 1000)
 (if(>(+ (car x) (car y) co) 1000)
    (big-add1 (cdr x) (cdr y) 1)
    (big-add1 (cdr x) (cdr y) 0))
    )

 ]
))