問題 2.41

;問題の意味が微妙にわからないが、
;多分、n以下の数i,j,kの和がもうひとつあたえられた数(s)と同じになればいい。
;1≦i<j<k≦nとする。

(define (enumerate-interval x n)
  (if (> x n) null (cons x (enumerate-interval (+ x 1) n))))

(define (accumulate op initial sequence)
  (if (null? sequence)
      initial
      (op (car sequence)
          (accumulate op initial (cdr sequence)))))

(define (filter condition seq)
  (accumulate (lambda (x y) (if (condition x) (cons x y) y))
              null
              seq))

(define (flatmap proc seq)
  (accumulate append null (map proc seq)))

(define (unique-three n)
  (flatmap
   (lambda (i)
     (flatmap
      (lambda (j) 
        (map (lambda (k) (list i j k))
             (enumerate-interval 1 (- j 1))))
      (enumerate-interval 1 (- i 1))))
   (enumerate-interval 1 n)))

(define (ex_2_41 n s)
  (accumulate
    (lambda (x y) 
      (if (= s (+ (car x) (car (cdr x)) (car (cdr (cdr x)))))
          (cons x y) y))
    null
    (unique-three n)))

(ex_2_41 10 17)
;-> ((7 6 4) (8 5 4) (8 6 3) (8 7 2) (9 5 3) (9 6 2) (9 7 1) (10 4 3) (10 5 2) (10 6 1))

(ex_2_41 15 27)
;-> ((10 9 8) (11 9 7) (11 10 6) (12 8 7) (12 9 6) (12 10 5) (12 11 4) (13 8 6) (139 5) (13 10 4) (13 11 3) (13 12 2) (14 7 6) (14 8 5) (14 9 4) (14 10 3) (14 11 2) (14 12 1) (15 7 5) (15 8 4) (15 9 3) (15 10 2) (15 11 1))

;okできてるみたい。

;(unique-three n)は処理を頭の中で追っていくとなかなか混乱する。
;内部の具体的処理まで脳内トレースしないで、たとえ再帰の中だろうと、
;ある程度の抽象的レベルで思考していくべきだと思った。

;いきなり難しくなったような。かなり時間かかってしまった。
;サラサラすすんでくつもりだったのに。