累积递归函数,产生一个从最后一个到第一个小计的列表。

问题描述 投票:1回答:1

试图这样做 '(3 2 1) -&gt.用累积递归的方法,我可以得到我想要的结果(算是)。'(6 3 1) 通过累积递归,我可以得到我想要的结果(某种程度上),我的意思是,我的首字母和尾字母似乎是按正确的顺序排列的,但我的 (cons 希望有一个列表,我给它一个数字。希望得到任何帮助。

如果我把 (cons(list 在助手和我 (reverseli 函数中的变量,我得到的是 '(6 3 1) 我想,但 (list (list (list '() 在前面。我只是想 '(6 3 1)

这是我所拥有的

(define (subtotal li)
  (subtotal-help (reverse li) 0))

(define (subtotal-help li acc)
  (cond
    [(empty? li) empty]
    [else  (list (subtotal-help (rest li)
                    (+ (first li) acc))
             (+ (first li) acc))]))
scheme racket
1个回答
2
投票

你应该使用 cons 来建立一个输出列表,而不是 list. 你的代码已经接近正确了,我们只需要调整一下位置,并增加一个额外的 reverse 在最后。

(define (subtotal li)
  (reverse
   (subtotal-help (reverse li) 0)))

(define (subtotal-help li acc)
  (cond
    [(empty? li) empty]
    [else (cons (+ (first li) acc)
                (subtotal-help (rest li) (+ (first li) acc)))]))

但如果你真的想要一个尾部递归的解决方案 那就需要更多的工作了。

(define (subtotal li)
  (cond
    [(empty? li) empty]
    [else (let ((lst (reverse li)))
            (subtotal-help (rest lst) (list (first lst))))]))

(define (subtotal-help li acc)
  (cond
    [(empty? li) acc]
    [else (subtotal-help (rest li)
                         (cons (+ (first li) (first acc))
                               acc))]))

不管是哪种方法,都能达到预期的效果

(subtotal '(3 2 1))
=> '(6 3 1)

1
投票

@ÓscarLópez的回答很好地回答了OP的直接问题 但还有其他的方法可以解决这个问题 但这可能不是OP的教授想要的

我们可以 map 在输入的列表上加上一系列的索引,使用 drop 以减少每个 apply 其余的列表汇总。在此 _x 是指通过以下方式从输入列表中获取的(被忽略的)值。map, n 是指元素的数量 dropxs 是输入列表。

(define (subtotal-list xs)
  (map (lambda (_x n)
         (apply + (drop xs n)))
       xs
       (range (length xs))))
scratch.rkt> (subtotal-list '(3 2 1))
'(6 3 1)
scratch.rkt> (subtotal-list '())
'()

顺便说一下,Common Lisp有一个很好的成语来形容这种事情,它的工作原理类似于使用 LOOP 宏。喏 x 不使用列表中的元素 xs列表,而是整个列表,并且在每次迭代时 x 通过使用 cdr (默认情况下)。

(defun subtotal-list-cl (xs)
  (loop
     :for x :on xs
     :collect (apply #'+ x)))
SCRATCH> (subtotal-list-cl '(3 2 1))
(6 3 1)
SCRATCH> (subtotal-list-cl '())
NIL

回到手头的任务,如果需要一个迭代帮助程序,以及如果: apply 允许,那么可以定义一个更简洁的尾部递归过程的版本。这里,由于中间结果是 cons蓄能器的前端,蓄能器的末端必须反转。

(define (subtotal-list-iter xs)
  (subtotal-list-helper xs '()))

(define (subtotal-list-helper xs acc)
  (if (null? xs) (reverse acc)
      (subtotal-list-helper (rest xs)
                            (cons (apply + xs) acc))))
scratch.rkt> (subtotal-list-iter '(3 2 1))
'(6 3 1)
scratch.rkt> (subtotal-list-iter '())
'()
© www.soinside.com 2019 - 2024. All rights reserved.