球拍捕捉功能的结果

时间:2015-09-04 04:30:30

标签: scheme racket

我正在创建一个手动添加大数字的功能(没有库功能),并且我在捕获要显示的结果时遇到一些麻烦。我只是显示回来#()。以下是它应该如何运作的一些背景:如果我通过(big-add1'(999)'(456)0),我应该返回'(455 1)。如果我通过(big-add1'(999 234 681)'(456)0)我应该返回'(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.它似乎执行该行,但实际上并没有改变它。任何人都可以澄清发生了什么事吗? 我对此非常陌生,所以如果有人对如何简化它有任何建议,请随时告诉我。我真的很感激。谢谢你的时间。

3 个答案:

答案 0 :(得分:3)

首先,代码中存在大量错误。我列出了几个大的:

  • Scheme不会返回,除非它是最后一个表达式。 第一个else子句cond表达式是典型的不返回。
  • append不会更改给定列表的内容。它是;; trying to...评论部分。不确定你想做什么。
  • 使用letrec什么都不做。如果要更改边界值,请使用set!

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

  • 您不必创建列表,然后append创建列表。只需使用list即可。使用cons构建列表,然后reverse结果是常用于返回列表的惯用法之一。因此,如果您看到使用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))))])))

答案 1 :(得分:2)

你看起来和我在同一个班级,所以我可以帮助你。上面的Takashi Kato已经回答了你关于球拍/方案如何返回结果的问题(只有最后一个表达式会返回结果),但我想我可以详细说明你想要达到的解决方案。

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

虽然加藤先生的解决方案可行,但奥斯汀博士(如果我们有相同的教授)会更喜欢你以递归的方式完成这个问题并以与传递的参数相同的格式返回答案in(&#34; chunks&#34;的列表)。提供的清单无需撤销即可。

这是一种思考方式:

  • 当您添加&#34; chunks&#34;数字的总和,你appendcons每个块的总和,以创建一个返回结果的列表。
  • 如果块的总和超过999,则表示它将具有遗留值。由于单个块的最大值为999,下一个块中的值1等于前一个块中的1000 - 这意味着您必须减去(或模数,无论您的偏好是什么,因为它们完成相同的任务)1000您当前的块,然后将值1传递给下一个计算。
  • 因此,当我们从每个列表中的每个块移动到下一个块时,每个块总和将是x块,y块和遗留值(如果有的话)的总和。

该算法看起来像这样:

  1. 通过将car xcar yco加在一起来计算块总和:(+ (car x) (car y) co)。您可以使用let将此值存储到ID中。我打电话给我chunk-sum,但你可以把它叫做任何让你更容易理解的东西。在let的正文中,您必须定义如何处理chunk-sum以及如何开始创建您返回的列表。
  2. 如果chunk-sum等于或大于1000或MAX_BLOCK_VALUE(如果您已定义该ID,则它们是等效的),则会有遗留值,因此您需要使用condif
  3. 使用appendcons创建列表。我发现cons更适合此解决方案,因为cons可以将数字元素作为其第一个参数,其中append仅采用列表(因此要求您在list上使用chunk-sum {1}})。在此步骤中,您必须递归调用函数big-add1以不断将元素追加到列表中。如果不完全相同,递归调用的代码看起来与(big-add1 (cdr x) (cdr y) 0)类似。
  4. 在我们到达基本案例后,该函数将返回一个值。在这种情况下,我们的基本情况是没有更多的块可以一起添加。
  5. 以下是您尝试完成的代码:

    #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")
               )
           )
         ]
        ))
    

    希望这有帮助。

答案 2 :(得分:0)

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

(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))
    )

 ]
))