2016-12-10 8 views
2

После записи последовательности Коллатца производящую функцию обычным способом:Как написать последовательность Collatz, используя разворачивающуюся схему/ракетку?

(define (colatz-seq #;[email protected] 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 #;[email protected] n) 
    (unfold one? next-colatz-step next-colatz-step n)) 

И это работает, как ожидалось, однако я не мог заставить его работать без используя «next-colatz-step» как второй, так и третий параметр разворачивания. Зачем? Кажется, странным является предоставление одного аргумента двум параметрам.

ответ

2

Обратите внимание, что в обоих ваших решениях вы исключаете исходный элемент в последовательности, а в решении 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) 
+0

почему: '(определить (один п) (список 1))' имеет п, как пары даже жесткий он не используется? – X10D

+0

@ X10D, потому что 'unfold' ожидает в качестве последнего аргумента процедуру с одним аргументом, но мы уже знаем, что последнее значение должно быть' 1'. Тем не менее, я обновил его, чтобы использовать параметр, в этот момент в рекурсии 'n'_is_' 1'. –