SICP問題3.70

merge手続きに似たmerge-weighted手続き

(define (merge-weighted s1 s2 weight)
  (cond ((stream-null? s1) s2)
        ((stream-null? s2) s1)
        (else
         (let ((s1car (stream-car s1))
               (s2car (stream-car s2)))
           (let ((s1weight (weight s1car))
                 (s2weight (weight s2car)))
             (if (< s1weight s2weight)
                 (cons-stream s1car (merge-weighted (stream-cdr s1) s2 weight))
                 (cons-stream s2car (merge-weighted s1 (stream-cdr s2) weight))))))))

i+jでの重み付けを行うための手続き

(define (i+j-weight x)
  (+ (car x) (cadr x)))

2i + 3j + 5ijでの重み付けを行うための手続き

(define (2i+3j+5ij-weight x)
  (let ((i (car x))
        (j (cadr x)))
    (+ (* 2 i) (* 3 j) (* 5 i j))))

重みに従って順序づけられた対のストリームを生成する手続きweight-pairs

(define (weighted-pairs s t weight)
  (cons-stream 
   (list (stream-car s) (stream-car t))
   (merge-weighted
    (stream-map (lambda (x) (list (stream-car s) x))
                (stream-cdr t))
    (weighted-pairs (stream-cdr s) (stream-cdr t) weight)
    weight)))

2, 3, 5で割り切れない整数を選ぶためのフィルタ手続き

(define (filter_not_divisible_2_3_5 s)
 (stream-filter
  (lambda (x)
    (not (or (= (remainder x 2) 0)
             (= (remainder x 3) 0)
             (= (remainder x 5) 0))))
  s))

a.和i + jに従って順序づけられた、i <= jなる正の整数の対(i, j)の全てのストリーム

(stream-ref-range (weighted-pairs integers integers i+j-weight) 0 20)
; (1 1)
; (1 2)
; (2 2)
; (1 3)
; (2 3)
; (1 4)
; (3 3)
; (2 4)
; (1 5)
; (3 4)
; (2 5)
; (1 6)
; (4 4)
; (3 5)
; (2 6)
; (1 7)
; (4 5)
; (3 6)
; (2 7)
; (1 8)
; #<undef>

b. 和2i + 3j + 5ijに従って順序づけられたi <= jで、iもjも2, 3, 5で割り切れない整数の対(i, j)の全てのストリーム

(stream-ref-range 
 (weighted-pairs (filter_not_divisible_2_3_5 integers)
                 (filter_not_divisible_2_3_5 integers) 2i+3j+5ij-weight)
 0 20)
; (1 1)
; (1 7)
; (1 11)
; (1 13)
; (1 17)
; (1 19)
; (1 23)
; (1 29)
; (1 31)
; (7 7)
; (1 37)
; (1 41)
; (1 43)
; (1 47)
; (1 49)
; (1 53)
; (7 11)
; (1 59)
; (1 61)
; (7 13)
; #<undef>