Advertisement
timothy235

sicp-2-2-3-sequences-as-interfaces

Feb 23rd, 2016
277
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 9.42 KB | None | 0 0
  1. #lang racket
  2.  
  3. (require math/number-theory) ; for prime? used in 2.40
  4.  
  5. ;;;;;;;;;;
  6. ;; 2.33 ;;
  7. ;;;;;;;;;;
  8.  
  9. (define (accumulate op initial sequence)
  10.   (if (empty? sequence)
  11.     initial
  12.     (op (first sequence)
  13.         (accumulate op initial (rest sequence)))))
  14.  
  15. (define (my-map p sequence)
  16.   (accumulate (lambda (x y) (cons (p x) y)) empty sequence))
  17.  
  18. (my-map sqr (list 1 2 3))
  19. ;; '(1 4 9)
  20.  
  21. (define (my-append seq1 seq2)
  22.   (accumulate cons seq2 seq1))
  23.  
  24. (my-append (list 1 2 3) (list 4 5 6))
  25. ;; '(1 2 3 4 5 6)
  26.  
  27. (define (my-length sequence)
  28.   (accumulate (lambda (x y) (add1 y)) 0 sequence))
  29.  
  30. (my-length (list 1 2 3 4))
  31. ;; 4
  32.  
  33. ;;;;;;;;;;
  34. ;; 2.34 ;;
  35. ;;;;;;;;;;
  36.  
  37. (define (horner-eval x coefficient-sequence)
  38.   (accumulate (lambda (this-coeff higher-terms)
  39.                 (+ this-coeff (* x higher-terms)))
  40.               0
  41.               coefficient-sequence))
  42.  
  43. (horner-eval 2 (list 1 3 0 5 0 1)) ; 1 + 3 * 2 + 5 * 2 ^ 3 + 2 ^ 5 = 79
  44. ;; 79
  45.  
  46. ;;;;;;;;;;
  47. ;; 2.35 ;;
  48. ;;;;;;;;;;
  49.  
  50. (define (enumerate-tree tree)
  51.   (cond [(empty? tree) empty]
  52.         [(not (pair? tree)) (list tree)]
  53.         [else (append (enumerate-tree (first tree))
  54.                       (enumerate-tree (rest tree)))]))
  55.  
  56. (define (count-leaves t)
  57.   (accumulate +
  58.               0
  59.               (map (lambda (x) 1) (enumerate-tree t))))
  60.  
  61. (count-leaves (list (list 1 2) (list 3 (list 4 5))))
  62. ;; 5
  63.  
  64. ;;;;;;;;;;
  65. ;; 2.36 ;;
  66. ;;;;;;;;;;
  67.  
  68. (define (accumulate-n op init seqs)
  69.   (if (empty? (first seqs))
  70.     empty
  71.     (cons (accumulate op init (map first seqs))
  72.           (accumulate-n op init (map rest seqs)))))
  73.  
  74. (accumulate-n +
  75.               0
  76.               (list (list 1 2 3)
  77.                     (list 4 5 6)
  78.                     (list 7 8 9)))
  79. ;; '(12 15 18)
  80.  
  81. ;;;;;;;;;;
  82. ;; 2.37 ;;
  83. ;;;;;;;;;;
  84.  
  85. (define (dot-product v w)
  86.   (accumulate + 0 (map * v w)))
  87.  
  88. (dot-product (list 1 2) (list 4 5))
  89. ;; 14
  90.  
  91. (define (matrix-*-vector m v)
  92.   (map (lambda (row) (dot-product row v))
  93.        m))
  94.  
  95. (matrix-*-vector (list (list 1 2 3)
  96.                        (list 4 5 6)
  97.                        (list 7 8 9))
  98.                  (list 1 1 1))
  99. ;; '(6 15 24)
  100.  
  101. (define (transpose mat)
  102.   (accumulate-n cons
  103.                 empty
  104.                 mat))
  105.  
  106. (transpose (list (list 1 2 3)
  107.                  (list 4 5 6)
  108.                  (list 7 8 9)))
  109. ;; '((1 4 7) (2 5 8) (3 6 9))
  110.  
  111. (define (matrix-*-matrix m n)
  112.   (define cols (transpose n))
  113.   (map (lambda (row) (matrix-*-vector cols row))
  114.        m))
  115.  
  116. (matrix-*-matrix (list (list 1 2 3)
  117.                        (list 4 5 6)
  118.                        (list 7 8 9))
  119.                  (list (list 0 1 0)
  120.                        (list 0 0 1)
  121.                        (list 1 0 0)))
  122. ;; '((3 1 2) (6 4 5) (9 7 8))
  123.  
  124. ;;;;;;;;;;
  125. ;; 2.38 ;;
  126. ;;;;;;;;;;
  127.  
  128. (define fold-right accumulate)
  129.  
  130. (define (fold-left op initial sequence)
  131.   (define (iter result rst)
  132.     (if (null? rst)
  133.       result
  134.       (iter (op result (first rst))
  135.             (rest rst))))
  136.   (iter initial sequence))
  137.  
  138. (fold-right / 1 (list 1 2 3)) ; 1 / (2 / (3 / 1))
  139. ;; 3/2
  140. (fold-left / 1 (list 1 2 3)) ; ((1 / 1) / 2) / 3
  141. ;; 1/6
  142. (fold-right list empty (list 1 2 3))
  143. ;; '(1 (2 (3 ())))
  144. (fold-left list empty (list 1 2 3))
  145. ;; '(((() 1) 2) 3)
  146.  
  147. ;; If op is associative and initial is an identity for op, then fold-right and
  148. ;; fold-left will produce the same value for any sequence.  Also note that
  149. ;; fold-left is constant space but fold-right is linear space.
  150.  
  151. ;;;;;;;;;;
  152. ;; 2.39 ;;
  153. ;;;;;;;;;;
  154.  
  155. (define (reverse1 sequence)
  156.   (fold-right (lambda (x y) (append y (list x)))
  157.               empty
  158.               sequence))
  159.  
  160. (reverse1 (list 1 2 3))
  161. ;; '(3 2 1)
  162.  
  163. (define (reverse2 sequence)
  164.   (fold-left (lambda (x y) (cons y x))
  165.             empty
  166.              sequence))
  167.  
  168. (reverse2 (list 1 2 3))
  169. ;; '(3 2 1)
  170.  
  171. ;;;;;;;;;;
  172. ;; 2.40 ;;
  173. ;;;;;;;;;;
  174.  
  175. (define (enumerate-interval low high)
  176.   (if (> low high)
  177.     empty
  178.     (cons low (enumerate-interval (add1 low) high))))
  179.  
  180. (define (flatmap proc seq) ; only sensible when proc returns a list
  181.   (accumulate append empty (map proc seq)))
  182.  
  183. (define (prime-sum? pair)
  184.   (prime? (+ (first pair) (second pair))))
  185.  
  186. (define (make-pair-sum pair)
  187.   (list (first pair) (second pair) (+ (first pair) (second pair))))
  188.  
  189. (define (unique-pairs n)
  190.   (flatmap (lambda (i)
  191.              (map (lambda (j) (list i j))
  192.                   (enumerate-interval 1 (sub1 i))))
  193.            (enumerate-interval 1 n)))
  194.  
  195. (unique-pairs 5)
  196. ;; '((2 1) (3 1) (3 2) (4 1) (4 2) (4 3) (5 1) (5 2) (5 3) (5 4))
  197.  
  198. ;; A more Racketeering way of writing unique-pairs would be to use the built-in
  199. ;; list comprehensions:
  200.  
  201. (define (racket-unique-pairs n)
  202.   (for*/list ([i (in-range 1 (add1 n))]
  203.               [j (in-range 1 i)])
  204.              (list i j)))
  205.  
  206. (racket-unique-pairs 5)
  207. ;; '((2 1) (3 1) (3 2) (4 1) (4 2) (4 3) (5 1) (5 2) (5 3) (5 4))
  208.  
  209. (define (prime-sum-pairs n)
  210.   (map make-pair-sum (filter prime-sum? (unique-pairs n))))
  211.  
  212. (prime-sum-pairs 5)
  213. ;; '((2 1 3) (3 2 5) (4 1 5) (4 3 7) (5 2 7))
  214.  
  215. ;;;;;;;;;;
  216. ;; 2.41 ;;
  217. ;;;;;;;;;;
  218.  
  219. (define (sum-triples n s)
  220.   (filter (lambda (triple) (= (apply + triple) s))
  221.           (for*/list ([i (in-range 1 (add1 n))]
  222.                       [j (in-range 1 i)]
  223.                       [k (in-range 1 j)])
  224.                      (list k j i))))
  225.  
  226. (sum-triples 9 12)
  227. ;; '((3 4 5) (2 4 6) (1 5 6) (2 3 7) (1 4 7) (1 3 8) (1 2 9))
  228.  
  229. ;;;;;;;;;;
  230. ;; 2.42 ;;
  231. ;;;;;;;;;;
  232.  
  233. (define (queens board-size)
  234.   (define (queen-cols k)
  235.     (if (zero? k)
  236.       (list empty-board)
  237.       (filter (lambda (positions) (safe? k positions))
  238.               (flatmap (lambda (rest-of-queens)
  239.                          (map (lambda (new-row)
  240.                                 (adjoin-position new-row k rest-of-queens))
  241.                               (enumerate-interval 1 board-size)))
  242.                        (queen-cols (sub1 k))))))
  243.   (queen-cols board-size))
  244.  
  245. ;; A queen is a list of row and column coordinates.  A position is a list of queens.
  246.  
  247. (define empty-board empty)
  248.  
  249. (define (make-queen column row) (list column row))
  250. (define (col-coord queen) (first queen))
  251. (define (row-coord queen) (second queen))
  252.  
  253. (define (adjoin-position column row position)
  254.   (cons (make-queen column row) position))
  255.  
  256. (define (safe? k position)
  257.   ; #t if the first queen in position is safe from the other k - 1 queens
  258.   (define (safe-from-one? queen1 queen2)
  259.     (and (not (= (col-coord queen1)
  260.                  (col-coord queen2)))
  261.          (not (= (row-coord queen1)
  262.                  (row-coord queen2)))
  263.          (not (= (abs (- (col-coord queen1) ; different diagonals
  264.                          (col-coord queen2)))
  265.                  (abs (- (row-coord queen1)
  266.                          (row-coord queen2)))))))
  267.   (andmap (lambda (q) (safe-from-one? (first position) q))
  268.           (rest position)))
  269.  
  270. (queens 3)
  271. ;; '()
  272.  
  273. (queens 4)
  274. ;; '(((3 4) (1 3) (4 2) (2 1)) ((2 4) (4 3) (1 2) (3 1)))
  275.  
  276. (queens 5)
  277. ;; '(((4 5) (2 4) (5 3) (3 2) (1 1))
  278.   ;; ((3 5) (5 4) (2 3) (4 2) (1 1))
  279.   ;; ((5 5) (3 4) (1 3) (4 2) (2 1))
  280.   ;; ((4 5) (1 4) (3 3) (5 2) (2 1))
  281.   ;; ((5 5) (2 4) (4 3) (1 2) (3 1))
  282.   ;; ((1 5) (4 4) (2 3) (5 2) (3 1))
  283.   ;; ((2 5) (5 4) (3 3) (1 2) (4 1))
  284.   ;; ((1 5) (3 4) (5 3) (2 2) (4 1))
  285.   ;; ((3 5) (1 4) (4 3) (2 2) (5 1))
  286.   ;; ((2 5) (4 4) (1 3) (3 2) (5 1)))
  287.  
  288. (queens 6)
  289. ;; '(((5 6) (3 5) (1 4) (6 3) (4 2) (2 1))
  290.   ;; ((4 6) (1 5) (5 4) (2 3) (6 2) (3 1))
  291.   ;; ((3 6) (6 5) (2 4) (5 3) (1 2) (4 1))
  292.   ;; ((2 6) (4 5) (6 4) (1 3) (3 2) (5 1)))
  293.  
  294. ;;;;;;;;;;
  295. ;; 2.43 ;;
  296. ;;;;;;;;;;
  297.  
  298. (define (slow-queens board-size)
  299.   (define (slow-queen-cols k)
  300.     (if (zero? k)
  301.       (list empty-board)
  302.       (filter (lambda (positions) (safe? k positions))
  303.               (flatmap (lambda (new-row)
  304.                          (map (lambda (rest-of-queens)
  305.                                 (adjoin-position new-row k rest-of-queens))
  306.                               (slow-queen-cols (sub1 k))))
  307.                        (enumerate-interval 1 board-size)))))
  308.   (slow-queen-cols board-size))
  309.  
  310. ;; Interchanging the order of the loops causes the program to needlessly repeat
  311. ;; the call to queen-cols(k - 1) board-size times, for each new column k.  But
  312. ;; it's even worse than that, because each one of those calls causes the program
  313. ;; to needlessly repeat all the recursive calls to queen-cols(j) for smaller j.
  314.  
  315. ;; I'm not really sure what that does to the overall run time of queens(n).  I
  316. ;; think it should be increased by a factor = 1 + n + n ^ 2 + ... + n ^ (n - 1)
  317. ;; which is on the order of n ^ (n - 1), but I couldn't get enough run times to
  318. ;; really test that.
  319.  
  320. (for ([n (in-range 6 10)])
  321.   (define fast-start-time (current-inexact-milliseconds))
  322.   (define fast-num-solns (queens n))
  323.   (define fast-time (- (current-inexact-milliseconds) fast-start-time))
  324.   (define slow-start-time (current-inexact-milliseconds))
  325.   (define slow-num-solns (slow-queens n))
  326.   (define slow-time (- (current-inexact-milliseconds) slow-start-time))
  327.   (printf "~a ~a ~a ~a ~a ~a ~n"
  328.           n
  329.           (length fast-num-solns)
  330.           (round fast-time)
  331.           (length slow-num-solns)
  332.           (round slow-time)
  333.           (round (/ slow-time fast-time))))
  334.  
  335. ;;   n   solns1   fast-time   solns2   slow-time   ratio
  336. ;;   6   4        1.0         4        101.0       101.0
  337. ;;   7   40       3.0         40       1571.0      523.0
  338. ;;   8   92       15.0        92       32677.0     2252.0
  339. ;;   9   352      82.0        352      776164.0    9459.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement