計算機プログラムの構造と解釈 第二版 P204 問題3.74

問題は二つ

1. 教科書に定義があるsign-change-dector手続きをつくる。


2. 下記のの部分を埋める

;(define zero-crossings
;  (stream-map sign-change-detector sense-data <expression>))

という問題。

まず、1から
sign-change-dectorは割と簡単。
注意しないといけないのは、2つと引数どっちが今の値か、どっちが前の値か
これは、Alyssaがつくったmake-zero-crossingsを見ればわかる。


2は結構難しくて、ヒントは、
Alyssaがつくったzero-crossing手続きのなかでのmake-zero-crossing手続き。
この手続きの中で、last-valueの初期値を0にしているところだと思った。
はsense-dataより一個前の値を返すようにすればよいから、sense-dataの先頭に初期値として0を与えておけば良いかと思う。


ここではsense-dataとしてsinを使いました。

#!/usr/local/bin/gosh
;; -*- coding: utf-8 -*-

(load "./modules/stream.scm")


(define ones (cons-stream 1 ones))

(define (add-streams s1 s2)
  (stream-map + s1 s2))

(define integers (cons-stream 1 (add-streams ones integers)))



;;ストリームを見るための便利機能
(define (stream-viewer stream start count)

  (define (stream-initializer stream init-num)
    (if (= init-num 0) stream
      (stream-initializer (stream-cdr stream) (- init-num 1))))

  (define (show-stream stream count)
    (if (= count 0) (print "end")
      (begin
        (print (stream-car stream))
        (show-stream (stream-cdr stream) (- count 1)))))

  (begin
    (print "start")
    (show-stream (stream-initializer stream start) count)))


(define (sign-change-detector new-value old-value)
  (cond ((and (>= new-value 0) (< old-value 0)) 1)
        ((and (< new-value 0) (>= old-value 0)) -1)
        (else 0)))



(define sense-data
  (stream-map (lambda (x) (sin x)) integers))




;; Alyssa
(define (make-zero-crossings input-stream last-value)
  (cons-stream
    (sign-change-detector (stream-car input-stream) last-value)
    (make-zero-crossings (stream-cdr input-stream)
                         (stream-car input-stream))))

(define zero-crossings-alyssa (make-zero-crossings sense-data 0))



;;単純にストリームから一個前の値がとれれば良い。
;;だから一個前のストリームはAlyssaの初期値を先頭に加えてやる
;(define zero-crossings
;  (stream-map sign-change-detector sense-data <expression>))

(define zero-crossings
  (stream-map sign-change-detector sense-data (cons-stream 0 sense-data)))




;; main
(define (main args)

  (print "tests for sign-change-detector")
  (display "(sign-change-detector 2 1): ")
  (print (sign-change-detector 2 1))
  (display "(sign-change-detector -0.1 0.5): ")
  (print (sign-change-detector -0.1 0.5))
  (display "(sign-change-detector -2 -0.1): ")
  (print (sign-change-detector -2 -0.1))
  (display "(sign-change-detector 0.2 -0.5): ")
  (print (sign-change-detector 0.2 -0.5))
  (display "(sign-change-detector 0 0): ")
  (print (sign-change-detector 0 0))
  (display "(sign-change-detector 0 -1): ")
  (print (sign-change-detector 0 -1))
  (display "(sign-change-detector -1 0): ")
  (print (sign-change-detector -1 0))
  (newline)

  (print "sense-data")
  (stream-viewer sense-data 0 10)
  (newline)

  (print "zero-crossings-alyssa")
  (stream-viewer zero-crossings-alyssa 0 10)
  (newline)

  (print "zero-crossings")
  (stream-viewer zero-crossings 0 10)
  (newline)

  0)


実行

tests for sign-change-detector
(sign-change-detector 2 1): 0
(sign-change-detector -0.1 0.5): -1
(sign-change-detector -2 -0.1): 0
(sign-change-detector 0.2 -0.5): 1
(sign-change-detector 0 0): 0
(sign-change-detector 0 -1): 1
(sign-change-detector -1 0): -1

sense-data
start
0.8414709848078965
0.9092974268256817
0.1411200080598672
-0.7568024953079282
-0.9589242746631385
-0.27941549819892586
0.6569865987187891
0.9893582466233818
0.4121184852417566
-0.5440211108893699
end

zero-crossings-alyssa
start
0
0
0
-1
0
0
1
0
0
-1
end

zero-crossings
start
0
0
0
-1
0
0
1
0
0
-1
end

できていると思う。