如何在 scheme/racket 中使用 unfold 编写 Collatz 序列?
how to write Collatz sequence using unfold in scheme/racket?
以常规方式编写 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))))))
我想用unfold来写:
(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" 作为展开的第二个和第三个参数的情况下使其工作。为什么?
为两个参数提供相同的参数似乎有点奇怪。
请注意,在您的两个解决方案中,您都排除了序列中的起始元素,并且在基于 unfold
的解决方案中,生成的序列以某种方式落后于一个位置,这就是为什么您必须通过 next-colatz-step
两次。
如果我们从给定的 n
数字开始,unfold
的第二个参数就是 identity
过程,这看起来更自然。但这给我们留下了最后一个值(应该总是 1
,假设 Collatz 猜想为真)现在丢失的问题。这就是为什么现在我们必须提供一个额外的过程来生成列表的尾部。试试这个:
(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)
以常规方式编写 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))))))
我想用unfold来写:
(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" 作为展开的第二个和第三个参数的情况下使其工作。为什么? 为两个参数提供相同的参数似乎有点奇怪。
请注意,在您的两个解决方案中,您都排除了序列中的起始元素,并且在基于 unfold
的解决方案中,生成的序列以某种方式落后于一个位置,这就是为什么您必须通过 next-colatz-step
两次。
如果我们从给定的 n
数字开始,unfold
的第二个参数就是 identity
过程,这看起来更自然。但这给我们留下了最后一个值(应该总是 1
,假设 Collatz 猜想为真)现在丢失的问题。这就是为什么现在我们必须提供一个额外的过程来生成列表的尾部。试试这个:
(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)