ex 2.17, 2.18, 2.20, 2.21, 2.22, 2.23, 2.24, 2.25, 2.26, 2.27, 2.28

;; sicp ex 2.17
;; 最後の要素だけからなるリストを返す
(define (last-pair l)
  (if (pair? (cdr l))
      (last-pair (cdr l))
      l))
;; sicp ex 2.18
;; 反復的
(define (reverse l)
  (define (iter l result)
    (if (null? l)
        result
        (iter (cdr l) (cons (car l) result))))
  (iter l '()))
;; sicp ex 2.20
(define (same-parity x . l)
  (define (same-parity-in l)
    (if (null? l)
        '()
        (if (eq? (even? x) (even? (car l)))
            (cons (car l) (same-parity-in (cdr l)))
            (same-parity-in (cdr l)))))
  (cons x (same-parity-in l)))
;; sicp ex 2.21
(define (square-list-a items)
  (if (null? items)
      '()
      (cons (* (car items) (car items))
            (square-list-a (cdr items)))))

(define (square-list-b items)
  (map (lambda (x) (* x x)) items))
;; sicp ex 2.22
(define (square-list-c items)
  (define (iter things answer)
    (if (null? things)
        answer
        (iter (cdr things)
              (cons (square (car things)) ;; <- (1)
                    answer))))
  (iter items '()))
;; (car things) にはリストの前の方から順番に入っていくから
;; answerの初期値を'()であるとき、<n>をリストのn番目とすると
;; (cons ... (cons <3> (cons <2> (cons <1> '()))))
;; となるので、当然逆順になってしまう。

;; 無理矢理、できた結果をreverseすればいい?
(define (square-list-c2 items)
  (define (iter things answer)
    (if (null? things)
        answer
        (iter (cdr things)
              (cons (square (car things)) ;; <- (1)
                    answer))))
  (reverse (iter items '())))


(define (square-list-d items)
  (define (iter things answer)
    (if (null? things)
        answer
        (iter (cdr things)
              (cons answer
                    (square (car things))))))
  (iter items '()))

;; consによるリストでないもののリストへの追加は前方からしかできない。
;; リストへ後方から追加したものはリストにはならない。
;; (((((() . 1) . 4) . 9) . 16) . 25)
;; こんな結果になります。

;; append 使うとできるよ!!
(define (square-list-d2 items)
  (define (iter things answer)
    (if (null? things)
        answer
        (iter (cdr things)
              (append answer
                      (cons (square (car things)) '())))))
  (iter items '()))
;; sicp ex 2.23
;; for-eachの実装
(define (my-for-each proc items)
  (if (null? items)
      #t
      (cons (proc (car items))
            (my-for-each proc (cdr items)))))

;; その2
;; procが#fを返すような関数では駄目なのでだめだな。
(define (my-for-each2 proc items)
  (if (and (proc (car items)) (null? (cdr items)))
      #t
      (my-for-each2 proc (cdr items))))
;; sicp ex 2.24
;; 手で書きました。省略。
;; sicp ex 2.25
;; (1 3 (5 7) 9)
(car (cdr (car (cdr (cdr '(1 3 (5 7) 9))))))
;; ((7))
(car (car '((7))))
;; (1 (2 (3 (4 (5 (6 7))))))
(car (cdr (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr '(1 (2 (3 (4 (5 (6 7))))))))))))))))))
;; sicp ex 2.26
(define x (list 1 2 3))
(define y (list 4 5 6))

(append x y) ;; =>(1 2 3 4 5 6)
(cons x y) ;; => ((1 2 3) 4 5 6)
(list x y) ;; => ((1 2 3) (4 5 6))
;; sicp ex 2.27
(define (reverse l)
  (define (iter l result)
    (if (null? l)
        result
        (iter (cdr l) (cons (car l) result))))
  (iter l '()))


(define (deep-reverse items)
  (define (iter l result)
    (if (null? l)
        result
        (iter (cdr l) (cons (if (pair? (car l))
                                (deep-reverse (car l))
                                (car l))
                            result))))
  (iter items '()))
;; sicp ex 2.28
;; xがnullだったときは '()
;; xがペアだったときは(fringe (car x))と(fringe (cdr x))を連結したもの
;; xがペアでない場合は(cons x '()) すなわち、x一つからなるリスト
(define (fringe x)
  (cond ((null? x) '())
        ((pair? x) (append (fringe (car x)) (fringe (cdr x))))
        (else (cons x '()))))

ながい...


量が多いので時間切れになってしまったけど、
特に詰まらずに問題を消化できた。


良い感じ。