如何在scheme/racket中使用展开编写Collatz序列?
以常规方式写入Collatz序列生成函数后:如何在scheme/racket中使用展开编写Collatz序列?,scheme,racket,collatz,Scheme,Racket,Collatz,以常规方式写入Collatz序列生成函数后: (define (colatz-seq #;starting@ n) (cond ((= n 1) '()) ((even? n) (cons (/ n 2) (colatz-seq (/ n 2)))) ((odd? n) (cons (+ (* n 3) 1) (colatz-seq (+ (* n 3) 1)))))) 我想用“展开”来写它: (define (next-colatz-step n) (
(define (colatz-seq #;starting@ n)
(cond ((= n 1) '())
((even? n) (cons (/ n 2) (colatz-seq (/ n 2))))
((odd? n) (cons (+ (* n 3) 1) (colatz-seq (+ (* n 3) 1))))))
我想用“展开”来写它:
(define (next-colatz-step n)
(cond ((even? n) (/ n 2))
((odd? n) (+ (* n 3) 1))))
(define (one? n)
(= n 1))
(define (colatz-seq #;starting@ n)
(unfold one? next-colatz-step next-colatz-step n))
它可以像预期的那样工作,但是如果不使用“next colatz step”作为展开的第二个和第三个参数,我就无法让它工作。为什么?
为两个参数提供相同的参数似乎有点奇怪。请注意,在两个解决方案中,您都排除了序列中的起始元素,而在基于
展开的解决方案中,生成的序列在某种程度上落后于一个位置,这就是为什么您必须两次通过下一个colatz步骤
如果我们从给定的n
数字开始,那么unfold
的第二个参数就是identity
过程,这似乎更自然。但这就给我们留下了一个问题,即最后一个值(假定Collatz猜想为真,则该值应始终为1
)现在丢失了。这就是为什么现在我们必须提供一个额外的过程来生成列表的尾部。试试这个:
(require srfi/1)
(define (one? n)
(= n 1))
(define (next-collatz-step n)
(cond ((even? n) (/ n 2))
(else (+ (* 3 n) 1))))
(define (last-value n)
(list n))
(define (collatz-seq n)
(unfold one? identity next-collatz-step n last-value))
(collatz-seq 10)
=> '(10 5 16 8 4 2 1)
为什么:(定义(一个n)(列表1))
将n作为参数,即使它不被使用?@X10D这是因为展开
希望将一个arg过程作为其最后一个参数,但我们已经知道最后一个值必须是1
。但是,我更新了它以使用参数,在递归中的该点n
是1
。也可以将collatz seq
的主体写为(展开一个?标识下一个collatz步骤n列表)
。