Scheme 累积递归函数,用于生成从最后一个到第一个小计的列表

Scheme 累积递归函数,用于生成从最后一个到第一个小计的列表,scheme,racket,Scheme,Racket,尝试使用累积递归执行此操作(3 2 1)->'(6 3 1) 我可以得到我想要的结果(某种程度上),我的意思是我的第一次和休息似乎顺序正确,但我的(cons需要一个列表,我会给它一个数字。任何帮助都将不胜感激 如果我在助手中用(list)替换(cons,在函数中用(reverse替换)li变量,我会得到我想要的(631),但是前面有(list)(list)(list')。我只想要(631) 这就是我所拥有的 (define (subtotal li) (subtotal-help (reve

尝试使用累积递归执行此操作(3 2 1)->
'(6 3 1)
我可以得到我想要的结果(某种程度上),我的意思是我的第一次和休息似乎顺序正确,但我的
(cons
需要一个列表,我会给它一个数字。任何帮助都将不胜感激

如果我在助手中用
(list
)替换
(cons
,在函数中用
(reverse
替换
)li
变量,我会得到我想要的
(631)
,但是前面有
(list)(list)(list')
。我只想要
(631)

这就是我所拥有的

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

您应该使用
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-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))))
但是如果您真的想要一个尾部递归解决方案,那么需要做更多的工作:

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

您应该使用
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-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))))
但是如果您真的想要一个尾部递归解决方案,那么需要做更多的工作:

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

@ÓscarLópez给出的好答案回答了OP的直接问题,但还有其他方法可以解决这个问题,而OP的教授可能并不完全想要解决这个问题

您可以
将输入列表和一系列索引映射到列表中,使用
拖放
减少每个
应用的列表,该列表将剩余列表相加。此处
\u x
是(忽略的)
map
从输入列表中获取的值,
n
是要
drop
的元素数,
xs
是输入列表:

(define (subtotal-list xs)
  (map (lambda (_x n)
         (apply + (drop xs n)))
       xs
       (range (length xs))))
scratch.rkt>(小计列表(3 2 1))
'(6 3 1)
scratch.rkt>(小计列表'())
'()
顺便说一句,Common Lisp有一个很好的习惯用法,它使用
循环
宏类似地工作。这里
x
不是从列表
xs
中获取元素,而是从整个列表中获取元素,并且在每次迭代时
x
都会通过使用
cdr
来减少(默认情况下):

SCRATCH>(分类汇总表cl'(3 2 1))
(6 3 1)
草稿>(小计列表cl'())
无
回到手头的作业,如果需要迭代辅助程序,并且允许使用
apply
,则可以定义更简洁的尾部递归程序版本。在这里,由于中间结果
cons
放在累加器的前面,累加器必须在末尾反转:

(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-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>(国际热核实验堆(iter)(3 2 1)小计清单)
'(6 3 1)
scratch.rkt>(iter'()小计列表)
'()

斯卡尔洛佩斯的好答案回答了OP的直接问题,但有其他方法来解决这个问题,而OP的教授可能并不完全想要解决这个问题

您可以
将输入列表和一系列索引映射到列表中,使用
拖放
减少每个
应用的列表,该列表将剩余列表相加。此处
\u x
是(忽略的)
map
从输入列表中获取的值,
n
是要
drop
的元素数,
xs
是输入列表:

(define (subtotal-list xs)
  (map (lambda (_x n)
         (apply + (drop xs n)))
       xs
       (range (length xs))))
scratch.rkt>(小计列表(3 2 1))
'(6 3 1)
scratch.rkt>(小计列表'())
'()
顺便说一句,Common Lisp有一个很好的习惯用法,它使用
循环
宏类似地工作。这里
x
不是从列表
xs
中获取元素,而是从整个列表中获取元素,并且在每次迭代时
x
都会通过使用
cdr
来减少(默认情况下):

SCRATCH>(分类汇总表cl'(3 2 1))
(6 3 1)
草稿>(小计列表cl'())
无
回到手头的作业,如果需要迭代辅助程序,并且允许使用
apply
,则可以定义更简洁的尾部递归程序版本。在这里,由于中间结果
cons
放在累加器的前面,累加器必须在末尾反转:

(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-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>(国际热核实验堆(iter)(3 2 1)小计清单)
'(6 3 1)
scratch.rkt>(iter'()小计列表)
'()

在这里使用累加器有什么意义?
小计帮助
不在尾部位置,因此此代码不是一个迭代过程。您可以使用
应用
?@exnihilo这是一个课堂问题。教授想要一个累加器式的帮助函数。我应该将0添加到1,1添加到2,2添加到3,然后生成列表。我是new到programming@exnihilo有一点。教授到处都是,随着校园的关闭,课堂是在线的。因此,他更让人困惑,因为他没有教任何新的东西。我认为先叫小计意味着它处于尾声。我必须做更多的研究。我几乎是在自学。@exnihilo The accumulator用于跟踪总和,而不是输出列表。我认为不需要编写尾部递归解决方案。@JezzLess我不确定“累积递归”是什么意思。是“尾部递归”吗?如果这是一个要求,那么看看我的第二个解决方案。否则使用第一个解决方案在这里使用累加器有什么意义?
小计帮助
不在尾部位置,因此此代码不是一个迭代过程。你能用
应用
?@exnihilo吗?这是一个课堂问题。教授想要一个累加器式的帮助程序函数。我应该将0添加到1,1添加到2,2添加到3,然后生成列表。我是新手programming@exnihilo有一点。教授到处都是,随着校园的关闭,课堂是在线的。因此,他更加困惑,因为他没有