反向列出连续平均值的方案
scheme listing sucessive averages in reverse
我正在尝试反向列出列表中元素的连续平均值,例如在列表 (1 2 3) 中我尝试得到 (3+2+1/3 2+1/2 1)这是我尝试使用代码的列表示例。
(list 2 3 4 5 6)
出于某种原因,返回的值为“(4 7/2 4 7/2 4)”。这是代码
(define (sucessive-avg lst)
(if (=(length lst) 1)
lst
(cons(avg(reverse lst)) (sucessive-avg(cdr(reverse lst))))))
问题不是来自我的 avg,所以我不知道它有什么问题
你会调用多少次reverse?尝试逐步执行您的代码以了解发生了什么。
您可以编写一个函数来收集列表的连续 CDR 的平均值,并使用反向列表调用它:
(define (successive-averages lst)
(if (null? lst)
lst
(cons (avg lst)
(successive-averages (rest lst))))
(successive-averages (reverse (list 2 3 4 5 6)))
@coredump 的回答是一个很好的开始,但它没有使用正确的尾递归,看起来它对列表的错误部分进行了平均
for example in a list of (1 2 3) i try to get (3+2+1/3 2+1/2 1)
要列表'(2 3 4 5 6)
我的答案会给你
'((avg '(2 3 4 5 6))
(avg '(2 3 4 5))
(avg '(2 3 4))
(avg '(2 3))
(avg '(2)))
这似乎更符合您的描述。
这是代码
(define (avg lst)
(/ (foldl + 0 lst)
(length lst)))
(define (successive-avg lst)
(define (iter res lst)
(if (empty? lst)
(reverse res)
(iter (cons (avg lst) res) (rest lst))))
(iter '() (reverse lst)))
(print (successive-avg '(2 3 4 5 6)))
输出
'(4 3 1/2 3 2 1/2 2)
您实际上根本不需要回忆反向或平均。您不需要平均值的原因是您可以保留 运行 总和(在我的代码中通过 lambda 链)和显式计数。并且感觉到您首先想要最深递归的结果,在您递归时将 运行 平均值计算到累加器上,从而为您提供正确的最终顺序。
(define (successiveAvg Lst)
(cond ((null? Lst)
(error "succesiveAvg requires a non-empty list"))
((fold (lambda (acc x)
(if acc (number? x) #f))
#t
Lst)
(error "succesiveAvg requires a list of numbers" Lst))
(else
(let ((inc (lambda (x)
(+ 1 x)))
(f (lambda (x)
(lambda (y) (+ x y)))))
(let loop ((acc '())
(c (lambda (x) x))
(L lst)
(i 1))
(if (null? L)
acc
(loop (cons (/ (c (car L)) i)
acc)
(f (c (car L)))
(cdr L)
(inc i))))))))
(successiveavg '(2 3 4 5 6))
;Value 3: (4 7/2 3 5/2 2)
我正在尝试反向列出列表中元素的连续平均值,例如在列表 (1 2 3) 中我尝试得到 (3+2+1/3 2+1/2 1)这是我尝试使用代码的列表示例。
(list 2 3 4 5 6)
出于某种原因,返回的值为“(4 7/2 4 7/2 4)”。这是代码
(define (sucessive-avg lst)
(if (=(length lst) 1)
lst
(cons(avg(reverse lst)) (sucessive-avg(cdr(reverse lst))))))
问题不是来自我的 avg,所以我不知道它有什么问题
你会调用多少次reverse?尝试逐步执行您的代码以了解发生了什么。
您可以编写一个函数来收集列表的连续 CDR 的平均值,并使用反向列表调用它:
(define (successive-averages lst)
(if (null? lst)
lst
(cons (avg lst)
(successive-averages (rest lst))))
(successive-averages (reverse (list 2 3 4 5 6)))
@coredump 的回答是一个很好的开始,但它没有使用正确的尾递归,看起来它对列表的错误部分进行了平均
for example in a list of (1 2 3) i try to get (3+2+1/3 2+1/2 1)
要列表'(2 3 4 5 6)
我的答案会给你
'((avg '(2 3 4 5 6))
(avg '(2 3 4 5))
(avg '(2 3 4))
(avg '(2 3))
(avg '(2)))
这似乎更符合您的描述。
这是代码
(define (avg lst)
(/ (foldl + 0 lst)
(length lst)))
(define (successive-avg lst)
(define (iter res lst)
(if (empty? lst)
(reverse res)
(iter (cons (avg lst) res) (rest lst))))
(iter '() (reverse lst)))
(print (successive-avg '(2 3 4 5 6)))
输出
'(4 3 1/2 3 2 1/2 2)
您实际上根本不需要回忆反向或平均。您不需要平均值的原因是您可以保留 运行 总和(在我的代码中通过 lambda 链)和显式计数。并且感觉到您首先想要最深递归的结果,在您递归时将 运行 平均值计算到累加器上,从而为您提供正确的最终顺序。
(define (successiveAvg Lst)
(cond ((null? Lst)
(error "succesiveAvg requires a non-empty list"))
((fold (lambda (acc x)
(if acc (number? x) #f))
#t
Lst)
(error "succesiveAvg requires a list of numbers" Lst))
(else
(let ((inc (lambda (x)
(+ 1 x)))
(f (lambda (x)
(lambda (y) (+ x y)))))
(let loop ((acc '())
(c (lambda (x) x))
(L lst)
(i 1))
(if (null? L)
acc
(loop (cons (/ (c (car L)) i)
acc)
(f (c (car L)))
(cdr L)
(inc i))))))))
(successiveavg '(2 3 4 5 6))
;Value 3: (4 7/2 3 5/2 2)