増減を繰り返す整数のリストを作る

ちょっと面白いことをやってるのを見つけた。

 cf. 往復運動(レシプロ運動)を表現する連番リストを作る(srfi-1 iota の変種) – 分室の分室

リストを作るんであれば unfold が使えると思ってやってみた。省略可能な引数 shift の処理には let-optionals* を使った。

(use srfi-1)

(define reciprocating-motion
  (lambda (count start step limit . restargs)
    (let-optionals* restargs ((shift 0))
      (unfold (lambda (seed) (zero? (car seed)))
              (lambda (seed) (+ (cadr seed) shift))
              (lambda (seed)
                (let* ((c (car seed))
                       (s (caddr seed))
                       (v (+ (cadr seed) s)))
                (cond
                  ((< v 0) (list (- c 1) (- 0 v) (* s -1)))
                  ((> v limit) (list (- c 1) (- limit (- v limit)) (* s -1)))
                  (else (list (- c 1) v s)))))
                    (list count start step)))))

(print (reciprocating-motion 20 5 3 30))
(print (reciprocating-motion 20 5 3 30 50))
(print (reciprocating-motion 20 5 -5 30))
takatoh@apostrophe $ gosh reciprocating-motion.scm
(5 8 11 14 17 20 23 26 29 28 25 22 19 16 13 10 7 4 1 2)
(55 58 61 64 67 70 73 76 79 78 75 72 69 66 63 60 57 54 51 52)
(5 0 5 10 15 20 25 30 25 20 15 10 5 0 5 10 15 20 25 30)

できてると思う。