(sicp35)m3.12~3.19

他の人って図の所はどうやって書いているんだろう?

(define orig-pair (cons '() '()))
(define (get-new-pair) orig-pair)
;;get-new-pairはlispの実装に必要らしい。
(define (my-cons x y)
  (let ((new (get-new-pair)))
    (set-car! new x)
    (set-cdr! new y)
    new))
(my-cons 3 4)

(define (my-append x y)
  (fold-right (lambda (x rest) (cons x rest)) y x))

(define (my-append! x y)
  (set-cdr! (my-last-pair x) y) x)

(define (my-last-pair seq)
  (let ((rest (cdr seq)))
  (if (null? rest)
      seq
      (my-last-pair rest))))

(define x (list 'a 'b))
(define y (list 'c 'd))

(define (report x y f)
  (let ((z (f x y)))
    (print "z= " z ": (cdr x)= " (cdr x))))

;;m3.12
(for-each (cut report x y <>)
          (list my-append my-append!))
;; 40:user> z= (a b c d): (cdr x)= (b)
;; z= (a b c d): (cdr x)= (b c d)

;;m3.13
(define (make-cycle x)
  (set-cdr! (last-pair x) x)
  x)


(define z (make-cycle (list 'a 'b 'c)))
	;;listで作っているのは、quoteで作ったリストは変更しない慣習だから?
	;;(equal? (list 'a 'b) '(a b)) ;;=> #t
	;;(equal? '((lambda ())) (list (lambda ()))) ;;=>#f
		;;関数になると挙動が少し変わってくる。

;(last-pair z) ;;どう考えても無限ループ(循環参照といものだと思う。)
;; a->b->c|
;; ^------  ;;こんな感じ

;;m3.14
(define (mystery x)
  (define (loop x y)
    (if (null? x)
        y
        (let ((temp (cdr x)))
          (set-cdr! x y)
          (loop temp x))))
  (loop x '()))

(let*((v (list 'a 'b 'c 'd))
     (w (mystery v)))
  (print "v : " v "w : " w))
	;;16:user> v : (a)w : (d c b a)
;;ポインタ図は書けないな-

;;m3.15
(define (set-to-wow! x)
  (set-car! (car x) 'wow) 
x)
(define x (list 'a 'b))
(define z1 (cons x x))
(define z2 (cons (list 'a 'b) (list 'a 'b)))

(for-each (lambda (x) (print (set-to-wow! x))) (list z1 z2))
;; 35:user> ((wow b) wow b)
;; ((wow b) a b)
	;;図は面倒なので省略。z1の方はxで値を共有しているから、set-car!で変更したとき、
	;;cdrの要素も変わった。

;;m3.16
(define (count-pairs x)
  (if (not (pair? x))
      0
      (+ (count-pairs (car x))
         (count-pairs (cdr x))
  1)))
(define a (cons 1 2))

;;3を返すのは
(define ret3 (list 1 2 3))
(count-pairs ret3)
	;; 1:user> => 3
;;4を返すのは
(define ret4
  (let ((lst (list 1 2 3)))
    (set-car! lst (last-pair lst))
    lst))
(count-pairs ret4)
	;; 3:user> => 4

;;7を返すのは
(define ret7
  (let ((lst (list 1 2 3)))
  (set-car! lst (cdr lst))
  (set-car! (cdr lst) (last-pair lst))
  lst))
(count-pairs ret7)
	;; 5:user> => 7
    
;;何も返さないって無限ループのこと?
(define no-ret
  (let ((lst (list 1 2 3)))
    (set-cdr! (last-pair lst) lst)
    lst))
;;(count-pairs no-ret)		;;無限ループ

;;m3.17
(define (my-count-pairs x)
  (let ((counted '()))
    (define (counted? item)
      (memq item counted))
    (define (loop x)
    (if (not (pair? x))
        0
        (let ((item (car x)))
        (if (counted? item)
            0
            (begin (set! counted (cons item counted))
                   (+ (loop item)
                      (loop (cdr x))
                      1))))))
    (loop x)))
(define rets (list ret3 ret4 ret7 no-ret))
(map my-count-pairs rets)
	;;22:user> => (3 3 3 3)

;;m3.18
(define (cycle? seq)
  (let ((memory '()))
  (define (loop x)
    (cond ((not (pair? x)) #f)
          ((memq x memory) #t)
          (else
           (set! memory (cons x memory))
           (or (cycle? (car x))
               (loop (cdr x))))))
  (loop seq)))
  

(map cycle? rets) ;;35:user> => (#f #f #f #t)

;;m3.19
;;多分こういうこと?
(define (cycle?2 seq)
    (define (loop x life)
      (cond ((not (pair? x)) #f)
            ((= 0 life) #t)
            (else
             (or (cycle?2 (car x))
                 (loop (cdr x) (- life 1))))))
    (loop seq 10000))
(map cycle?2 rets)	;; 11:user> => (#f #f #f #t)