球拍捕获功能的结果
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" 个数字相加时,您
append
或 cons
每个块的总和创建一个列表 return 您的结果.
- 如果块的总和超过 999,则意味着它将具有结转值。由于单个块的最大值为 999,因此下一个块中的值 1 等于前一个块中的 1000——这意味着您必须减去(或取模,无论您的偏好如何,因为它们完成相同的任务)1000 以内您当前的块,然后将值 1 传递给下一个计算。
- 因此,当我们从每个列表中的每个块移动到下一个时,每个块总和将是 x 块、y 块和结转值(如果有的话)的总和。
算法看起来像这样:
- 通过将
car x
、car y
和 co
相加来计算块总和:(+ (car x) (car y) co)
。您可以使用 let
将此值存储到 ID 中。我将我的名称命名为 chunk-sum
,但您可以将其命名为任何便于您理解的名称。在我们的 let
正文中,您必须定义如何处理我们的 chunk-sum
以及如何开始创建您 return. 的列表
- 如果
chunk-sum
等于或大于 1000 或 MAX_BLOCK_VALUE
(如果您定义了该 ID,它们是等效的),那么会有一个结转值,因此您需要使用 cond
或 if
.
- 使用
append
或 cons
创建列表。我发现 cons
更适合此解决方案,因为 cons
可以将数字元素作为其第一个参数,其中 append
仅采用列表(因此要求您在 chunk-sum
).在此步骤中,您将不得不递归调用函数 big-add1
以不断将元素添加到您的列表中。如果不完全相同,您的递归调用代码将类似于 (big-add1 (cdr x) (cdr y) 0)
。
- 函数将 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))
)
]
))
我正在制作一个手动将大数字相加的函数(没有库函数),但我在捕获要显示的结果时遇到了一些问题。我只是简单地向后显示'()。这是它应该如何工作的一些背景知识:如果我通过 (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" 个数字相加时,您
append
或cons
每个块的总和创建一个列表 return 您的结果. - 如果块的总和超过 999,则意味着它将具有结转值。由于单个块的最大值为 999,因此下一个块中的值 1 等于前一个块中的 1000——这意味着您必须减去(或取模,无论您的偏好如何,因为它们完成相同的任务)1000 以内您当前的块,然后将值 1 传递给下一个计算。
- 因此,当我们从每个列表中的每个块移动到下一个时,每个块总和将是 x 块、y 块和结转值(如果有的话)的总和。
算法看起来像这样:
- 通过将
car x
、car y
和co
相加来计算块总和:(+ (car x) (car y) co)
。您可以使用let
将此值存储到 ID 中。我将我的名称命名为chunk-sum
,但您可以将其命名为任何便于您理解的名称。在我们的let
正文中,您必须定义如何处理我们的chunk-sum
以及如何开始创建您 return. 的列表
- 如果
chunk-sum
等于或大于 1000 或MAX_BLOCK_VALUE
(如果您定义了该 ID,它们是等效的),那么会有一个结转值,因此您需要使用cond
或if
. - 使用
append
或cons
创建列表。我发现cons
更适合此解决方案,因为cons
可以将数字元素作为其第一个参数,其中append
仅采用列表(因此要求您在chunk-sum
).在此步骤中,您将不得不递归调用函数big-add1
以不断将元素添加到您的列表中。如果不完全相同,您的递归调用代码将类似于(big-add1 (cdr x) (cdr y) 0)
。 - 函数将 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))
)
]
))