計算機プログラムの構造と解釈 第二版 P72 問題2.40

実装

#!/usr/local/bin/gosh
;; -*- coding: utf-8 -*-

(use ggc.debug.trace)
(use math.mt-random)

(define nil '())

(define (square n)
  (* n n)) 


;;prime? の実装
(define (smallest-divisor n)
  (find-divisor n 2)) 

(define (divides? a b)
  (= (remainder b a) 0)) 


(define (find-divisor n test-divisor)
  (cond ((> (square test-divisor) n) n)
        ((divides?  test-divisor n) test-divisor)
        (else (find-divisor n (cond ((= test-divisor 2) 3 ) 
                                    (else (+ test-divisor 2)))))))
(define (prime? n)
  (cond ((= n (smallest-divisor n)) #t) 
  (else #f)))
;; prime?終わり。


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


(define (enumerate-interval low high)
  (if (> low high)
    nil
    (cons low (enumerate-interval (+ low 1) high))))


(define (filter predicate sequence)
  (cond ((null? sequence) nil)
        ((predicate (car sequence))
         (cons (car sequence)
               (filter predicate (cdr sequence))))
        (else (filter predicate (cdr sequence)))))


;;; Blow is the contents of p71-72
(define (flatmap proc seq)
  (accumulate append nil (map proc seq)))


(define (prime-sum? pair)
  (prime? (+ (car pair) (cadr pair))))


(define (make-pair-sum pair)
  (list (car pair) (cadr pair) (+ (car pair) (cadr pair))))


(define (permutations s)
  (if (null? s)
    (list nil)
    (flatmap (lambda (x)
               (map (lambda (p) (cons x p))
                    (permutations (remove x s))))
             s)))


(define (remove item sequence)
  (filter (lambda (x) (not (= x item)))
          sequence))



;これは参考までに解説の部分でのprime-sum-pairs
;(define (prime-sum-pairs n)
;  (map make-pair-sum
;       (filter prime-sum?
;               (flatmap
;                 (lambda (i)
;                   (map (lambda (j) (list i j))
;                        (enumerate-interval 1 (- i 1))))
;                 (enumerate-interval 1 n)))))


(define (enumerate-interval low high)
  (if (> low high)
    nil
    (cons low (enumerate-interval (+ low 1) high))))


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


(define (prime-sum-pairs n)
  (map make-pair-sum
       (filter prime-sum? (unique-pairs n))))

 
;; main
(define (main args)
  (display "この問題は今までのprime-sum-pairsの一部を切り取れば余裕")(newline)
  (display "良く分からない時は分割して考える")(newline)(newline)

  (display "まずは、enumerate-intervalの動き")(newline)
  (display "(enumerate-interval 1 5): ")
  (display (enumerate-interval 1 5))
  (newline)(newline)


  (display "次は、prime-sum-pairesの最も内側")(newline)
  (display "(map (lambda (j) (list 5 j)) (enumerate-interval 1 4)):")
  (newline)
  (display (map (lambda (j) (list 5 j)) (enumerate-interval 1 4)))
  (newline)(newline)


  (display "以下は、prime-sum-pairesの上のものの外側")(newline)
  (display "(map (lambda (i)
         (map (lambda (j) (list i j))
              (enumerate-interval 1 (- i 1))))
       (enumerate-interval 1 5)): ")
  (newline)
  (display (map (lambda (i)
         (map (lambda (j) (list i j))
              (enumerate-interval 1 (- i 1))))
       (enumerate-interval 1 5)))
  (newline)
  (newline)


  (display "上の出力だと、1の時のリスト、2の時のりすと、3の時のリスト...毎にリストになっているので")(newline)
  (display "flatmapで平らにするして名前をつけてやる。")(newline)
  (display "(unique-pairs 5): ")
  (display (unique-pairs 5))
 (newline)
  (newline)


  (display "そもそも、prime-sum-pairsの中身からとったので、対応する箇所に割り当てる。")(newline)
  (display "(prime-sum-pairs 5): ")
  (display (prime-sum-pairs 5))
  (newline)

  0)


実行

この問題は今までのprime-sum-pairsの一部を切り取れば余裕
良く分からない時は分割して考える

まずは、enumerate-intervalの動き
(enumerate-interval 1 5): (1 2 3 4 5)

次は、prime-sum-pairesの最も内側
(map (lambda (j) (list 5 j)) (enumerate-interval 1 4)):
((5 1) (5 2) (5 3) (5 4))

以下は、prime-sum-pairesの上のものの外側
(map (lambda (i)
         (map (lambda (j) (list i j))
              (enumerate-interval 1 (- i 1))))
       (enumerate-interval 1 5)): 
(() ((2 1)) ((3 1) (3 2)) ((4 1) (4 2) (4 3)) ((5 1) (5 2) (5 3) (5 4)))

上の出力だと、1の時のリスト、2の時のりすと、3の時のリスト...毎にリストになっているので
flatmapで平らにするして名前をつけてやる。
(unique-pairs 5): ((2 1) (3 1) (3 2) (4 1) (4 2) (4 3) (5 1) (5 2) (5 3) (5 4))

そもそも、prime-sum-pairsの中身からとったので、対応する箇所に割り当てる。
(prime-sum-pairs 5): ((2 1 3) (3 2 5) (4 1 5) (4 3 7) (5 2 7))

がんばっていたなぁ。