用于返回平方数列表之和的 Racket 递归函数
Racket recursive function for returning the sum of a list of squared numbers
我是 Racket 的新手,我正在尝试编写一个递归函数,它接受一个数字 n
和 returns 第一个 n
整数的平方和。例如,(this-function 3)
returns 14 因为 14 是 9 + 4 + 1 + 0。
我尝试创建两个单独的函数,一个对每个数字求平方,returns 一个平方数列表,第二个对列表求和。每个数字平方的函数是:
(define (squared my-list)
(cond [(empty? my-list) empty]
[(zero? my-list) 0]
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
如果我 运行 (squared 3)
returns (cons 9 (cons (cons 4 (cons (cons 1 (cons 0 empty)) empty)) empty))
.
当我运行第二个函数(求和函数)时:
(define (sum numbers)
(cond
[(empty? numbers) 0]
[else (+ (first numbers) (sum (rest numbers)))]))
和 运行 (sum (squared 3))
我收到一条错误消息,因为 (squared 3)
returns 列表中有一个额外的 "cons"。
我该如何解决这个问题?
最直接的解决方案是使用封闭形式:
(define (sum-of-squares n)
(* 1/6 n (+ n 1) (+ n n 1)))
来源:WolframAlpha
您在 squared
中的逻辑有点不对劲。我会逐条解释这些问题。
[(empty? my-list) empty]
这没有任何意义,因为 my-list
永远不会成为列表。事实上,my-list
命名不当。 squared
接受的参数是一个 数字 ,而不是一个列表。这个条款可以完全删除。
[(zero? my-list) 0]
这是 实际 终止案例应该是什么,但它不应该 return 0
。请记住,squared
必须 return 一个 list,而不是一个数字。 这个案例应该return empty
.
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
最后,这个条款太复杂了。您的想法是正确的 — cons
将新号码添加到列表的其余部分 — 但您的想法太多了。请记住,(squared (sub1 my-list))
的结果本身就是一个列表,而 cons
的第二个参数是列表的其余部分。你不需要额外的缺点——你可以完全消除它。
结合这些变化,你得到这个,它做你想要的:
(define (squared my-list)
(if (zero? my-list) empty
(cons (expt my-list 2)
(squared (sub1 my-list)))))
(我还用 if
替换了 cond
,因为不再需要 cond
。)
就是说,这段代码不是很 Racket-y。您有一个将函数分解为两个函数的好主意 — 在函数式编程中,函数实际上应该只做 一个 事情 — 但您可以进一步分解它!具体来说,你可以利用 Racket 的内置高阶函数来使这类事情变得非常容易。
您可以通过适当组合 map
and range
来替换整个 squared
功能。例如,下面创建一个从 0–3 的正方形列表。
(map (curryr expt 2) (range 4))
(您需要调用 (<a href="http://docs.racket-lang.org/reference/pairs.html?q=range#%28def._%28%28lib._racket%2Flist..rkt%29._range%29%29" rel="nofollow">range</a> 4)
because the list generated by range
从 0 到 n-1。)
接下来,您可以使用 apply
轻松对列表求和。总结上面的列表,你会做这样的事情:
(apply + (map (curryr expt 2) (range 4)))
这为您提供了 14
的适当结果。显然,为了清楚起见,您可以将它封装在它自己的函数中,但是一旦您了解了 Racket 的函数结构,上面的代码在做什么就清楚多了。
(但是,我不确定您是否可以使用这些,因为您的问题看起来很像家庭作业。只是为了将来的参考和完整性而注明。)
不需要一个提供正方形列表的函数和一个汇总列表的函数。
这将达到目的,并且根据需要递归。
(define (my-sq n)
(cond [(zero? n) 0]
[else
(+ (* n n) (my-sq (- n 1)))]))
(my-sq 3) -> 14
我是 Racket 的新手,我正在尝试编写一个递归函数,它接受一个数字 n
和 returns 第一个 n
整数的平方和。例如,(this-function 3)
returns 14 因为 14 是 9 + 4 + 1 + 0。
我尝试创建两个单独的函数,一个对每个数字求平方,returns 一个平方数列表,第二个对列表求和。每个数字平方的函数是:
(define (squared my-list)
(cond [(empty? my-list) empty]
[(zero? my-list) 0]
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
如果我 运行 (squared 3)
returns (cons 9 (cons (cons 4 (cons (cons 1 (cons 0 empty)) empty)) empty))
.
当我运行第二个函数(求和函数)时:
(define (sum numbers)
(cond
[(empty? numbers) 0]
[else (+ (first numbers) (sum (rest numbers)))]))
和 运行 (sum (squared 3))
我收到一条错误消息,因为 (squared 3)
returns 列表中有一个额外的 "cons"。
我该如何解决这个问题?
最直接的解决方案是使用封闭形式:
(define (sum-of-squares n)
(* 1/6 n (+ n 1) (+ n n 1)))
来源:WolframAlpha
您在 squared
中的逻辑有点不对劲。我会逐条解释这些问题。
[(empty? my-list) empty]
这没有任何意义,因为 my-list
永远不会成为列表。事实上,my-list
命名不当。 squared
接受的参数是一个 数字 ,而不是一个列表。这个条款可以完全删除。
[(zero? my-list) 0]
这是 实际 终止案例应该是什么,但它不应该 return 0
。请记住,squared
必须 return 一个 list,而不是一个数字。 这个案例应该return empty
.
[else (cons (expt my-list 2)
(cons (squared (sub1 my-list)) empty))]))
最后,这个条款太复杂了。您的想法是正确的 — cons
将新号码添加到列表的其余部分 — 但您的想法太多了。请记住,(squared (sub1 my-list))
的结果本身就是一个列表,而 cons
的第二个参数是列表的其余部分。你不需要额外的缺点——你可以完全消除它。
结合这些变化,你得到这个,它做你想要的:
(define (squared my-list)
(if (zero? my-list) empty
(cons (expt my-list 2)
(squared (sub1 my-list)))))
(我还用 if
替换了 cond
,因为不再需要 cond
。)
就是说,这段代码不是很 Racket-y。您有一个将函数分解为两个函数的好主意 — 在函数式编程中,函数实际上应该只做 一个 事情 — 但您可以进一步分解它!具体来说,你可以利用 Racket 的内置高阶函数来使这类事情变得非常容易。
您可以通过适当组合 map
and range
来替换整个 squared
功能。例如,下面创建一个从 0–3 的正方形列表。
(map (curryr expt 2) (range 4))
(您需要调用 (<a href="http://docs.racket-lang.org/reference/pairs.html?q=range#%28def._%28%28lib._racket%2Flist..rkt%29._range%29%29" rel="nofollow">range</a> 4)
because the list generated by range
从 0 到 n-1。)
接下来,您可以使用 apply
轻松对列表求和。总结上面的列表,你会做这样的事情:
(apply + (map (curryr expt 2) (range 4)))
这为您提供了 14
的适当结果。显然,为了清楚起见,您可以将它封装在它自己的函数中,但是一旦您了解了 Racket 的函数结构,上面的代码在做什么就清楚多了。
(但是,我不确定您是否可以使用这些,因为您的问题看起来很像家庭作业。只是为了将来的参考和完整性而注明。)
不需要一个提供正方形列表的函数和一个汇总列表的函数。 这将达到目的,并且根据需要递归。
(define (my-sq n)
(cond [(zero? n) 0]
[else
(+ (* n n) (my-sq (- n 1)))]))
(my-sq 3) -> 14