さかもとのブログ

つらつらと

SICP演習問題4.39,4.40,4.41,4.42

4.38はパス.めんどー.

4.39

影響しない(はず)

4.40

backerたちがそもそもすまないところは,始めからリストに入れない.

;exercise4.40
(define (multiple-dwelling)
  (let ((cooper (amb 2 3 4 5))
        (miller (amb 1 2 3 4 5)))
    (require (not (= cooper miller)))
    (require (> miller cooper))
    (let ((smith (amb 1 2 3 4 5)))
      (require (not (= smith cooper)))
      (require (not (= smith miller)))
      (let ((fletcher (amb 2 3 4)))
        (require (not (= fletcher cooper)))
        (require (not (= fletcher miller)))
        (require (not (= fletcher smith)))
        (require (not (= (abs (- fletcher smith)) 1)))
        (require (not (= (abs (- fletcher cooper)) 1)))
        (let ((backer (amb 1 2 3 4)))
          (require (not (= backer cooper)))
          (require (not (= backer miller)))
          (require (not (= backer smith)))
          (require (not (= backer fletcher)))
          (list (list 'backer backer)
                (list 'cooper cooper)
                (list 'fletcher fletcher)
                (list 'miller miller)
                (list 'smith smith)))))))
4.41

(やってないけど)4.38の確認も兼ねて,4.38の制限をコメントアウトした

;;exercise4.41
(use util.combinations)

(define (multiple-dwelling)
  (for-each (lambda (seq)
              (let ((backer   (car   seq))
                    (cooper   (cadr  seq))
                    (fletcher (caddr seq))
                    (miller   (cadddr seq))
                    (smith    (car (cddddr seq))))
                (if (and
                     (not (= backer 5))
                     (not (= cooper 1))
                     (not (= fletcher 5))
                     (not (= fletcher 1))
                     (> miller cooper)
;                    (not (= (abs (- smith fletcher)) 1))
                     (not (= (abs (- fletcher cooper)) 1)))
                    (print seq))))
              (permutations '(1 2 3 4 5))))
(time (multiple-dwelling))

gosh> (1 2 4 3 5)
(1 2 4 5 3)
(1 4 2 5 3)
(3 2 4 5 1)
(3 4 2 5 1)
;(time (multiple-dwelling))
; real   0.000
; user   0.000
; sys    0.000
#<undef>

ちなみに,letをlist-refでやると,

gosh> (1 2 4 3 5)
(1 2 4 5 3)
(1 4 2 5 3)
(3 2 4 5 1)
(3 4 2 5 1)
;(time (multiple-dwelling))
; real   0.010
; user   0.010
; sys    0.000
#<undef>

若干遅い.

4.42

一度ノートに解いて,その後4.41を使って解いてみた.
証言は排他的なので,xorを作成.

(use util.combinations)

(define (xor a b)
  (if (or (and a b) (and (not a) (not b))) #f #t))

(define (true-ranking-of-schoolgirls)
  (for-each (lambda (seq)
              (let ((betty  (car   seq))
                    (ethel  (cadr  seq))
                    (joan   (caddr seq))
                    (kitty  (cadddr seq))
                    (mary   (car (cddddr seq))))
                (if (and
                     (xor (= kitty 2) (= betty 3))
                     (xor (= ethel 1) (= joan  2))
                     (xor (= joan  3) (= ethel 5))
                     (xor (= kitty 2) (= mary  4))
                     (xor (= mary  4) (= betty 1)))
;                   (print seq))))
;                   (print (cons 'betty betty)
;                          (cons 'ethel ethel)
;                          (cons 'joan joan)
;                          (cons 'kitty kitty)
;                          (cons 'mary mary)))))
                    (print
                     (list 'betty betty
                           'ethel ethel
                           'joan  joan
                           'kitty kitty
                           'mary  mary)))))
              (permutations '(1 2 3 4 5))))
(time (true-ranking-of-schoolgirls))

;表示の時間も計測してみた
;(print seq)
;gosh> (3 5 2 1 4)
;(time (true-ranking-of-schoolgirls))
; real   0.000
; user   0.000
; sys    0.000
;#<undef>

;(print (cons ~))
;gosh> (betty . 3)(ethel . 5)(joan . 2)(kitty . 1)(mary . 4)
;(time (true-ranking-of-schoolgirls))
; real   0.010
; user   0.000
; sys    0.000
;#<undef>

;(print (list ~))
;gosh> (betty 3 ethel 5 joan 2 kitty 1 mary 4)
;(time (true-ranking-of-schoolgirls))
; real   0.000
; user   0.000
; sys    0.000