Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #lang racket
- (require math/number-theory) ; for prime? used in 2.40
- ;;;;;;;;;;
- ;; 2.33 ;;
- ;;;;;;;;;;
- (define (accumulate op initial sequence)
- (if (empty? sequence)
- initial
- (op (first sequence)
- (accumulate op initial (rest sequence)))))
- (define (my-map p sequence)
- (accumulate (lambda (x y) (cons (p x) y)) empty sequence))
- (my-map sqr (list 1 2 3))
- ;; '(1 4 9)
- (define (my-append seq1 seq2)
- (accumulate cons seq2 seq1))
- (my-append (list 1 2 3) (list 4 5 6))
- ;; '(1 2 3 4 5 6)
- (define (my-length sequence)
- (accumulate (lambda (x y) (add1 y)) 0 sequence))
- (my-length (list 1 2 3 4))
- ;; 4
- ;;;;;;;;;;
- ;; 2.34 ;;
- ;;;;;;;;;;
- (define (horner-eval x coefficient-sequence)
- (accumulate (lambda (this-coeff higher-terms)
- (+ this-coeff (* x higher-terms)))
- 0
- coefficient-sequence))
- (horner-eval 2 (list 1 3 0 5 0 1)) ; 1 + 3 * 2 + 5 * 2 ^ 3 + 2 ^ 5 = 79
- ;; 79
- ;;;;;;;;;;
- ;; 2.35 ;;
- ;;;;;;;;;;
- (define (enumerate-tree tree)
- (cond [(empty? tree) empty]
- [(not (pair? tree)) (list tree)]
- [else (append (enumerate-tree (first tree))
- (enumerate-tree (rest tree)))]))
- (define (count-leaves t)
- (accumulate +
- 0
- (map (lambda (x) 1) (enumerate-tree t))))
- (count-leaves (list (list 1 2) (list 3 (list 4 5))))
- ;; 5
- ;;;;;;;;;;
- ;; 2.36 ;;
- ;;;;;;;;;;
- (define (accumulate-n op init seqs)
- (if (empty? (first seqs))
- empty
- (cons (accumulate op init (map first seqs))
- (accumulate-n op init (map rest seqs)))))
- (accumulate-n +
- 0
- (list (list 1 2 3)
- (list 4 5 6)
- (list 7 8 9)))
- ;; '(12 15 18)
- ;;;;;;;;;;
- ;; 2.37 ;;
- ;;;;;;;;;;
- (define (dot-product v w)
- (accumulate + 0 (map * v w)))
- (dot-product (list 1 2) (list 4 5))
- ;; 14
- (define (matrix-*-vector m v)
- (map (lambda (row) (dot-product row v))
- m))
- (matrix-*-vector (list (list 1 2 3)
- (list 4 5 6)
- (list 7 8 9))
- (list 1 1 1))
- ;; '(6 15 24)
- (define (transpose mat)
- (accumulate-n cons
- empty
- mat))
- (transpose (list (list 1 2 3)
- (list 4 5 6)
- (list 7 8 9)))
- ;; '((1 4 7) (2 5 8) (3 6 9))
- (define (matrix-*-matrix m n)
- (define cols (transpose n))
- (map (lambda (row) (matrix-*-vector cols row))
- m))
- (matrix-*-matrix (list (list 1 2 3)
- (list 4 5 6)
- (list 7 8 9))
- (list (list 0 1 0)
- (list 0 0 1)
- (list 1 0 0)))
- ;; '((3 1 2) (6 4 5) (9 7 8))
- ;;;;;;;;;;
- ;; 2.38 ;;
- ;;;;;;;;;;
- (define fold-right accumulate)
- (define (fold-left op initial sequence)
- (define (iter result rst)
- (if (null? rst)
- result
- (iter (op result (first rst))
- (rest rst))))
- (iter initial sequence))
- (fold-right / 1 (list 1 2 3)) ; 1 / (2 / (3 / 1))
- ;; 3/2
- (fold-left / 1 (list 1 2 3)) ; ((1 / 1) / 2) / 3
- ;; 1/6
- (fold-right list empty (list 1 2 3))
- ;; '(1 (2 (3 ())))
- (fold-left list empty (list 1 2 3))
- ;; '(((() 1) 2) 3)
- ;; If op is associative and initial is an identity for op, then fold-right and
- ;; fold-left will produce the same value for any sequence. Also note that
- ;; fold-left is constant space but fold-right is linear space.
- ;;;;;;;;;;
- ;; 2.39 ;;
- ;;;;;;;;;;
- (define (reverse1 sequence)
- (fold-right (lambda (x y) (append y (list x)))
- empty
- sequence))
- (reverse1 (list 1 2 3))
- ;; '(3 2 1)
- (define (reverse2 sequence)
- (fold-left (lambda (x y) (cons y x))
- empty
- sequence))
- (reverse2 (list 1 2 3))
- ;; '(3 2 1)
- ;;;;;;;;;;
- ;; 2.40 ;;
- ;;;;;;;;;;
- (define (enumerate-interval low high)
- (if (> low high)
- empty
- (cons low (enumerate-interval (add1 low) high))))
- (define (flatmap proc seq) ; only sensible when proc returns a list
- (accumulate append empty (map proc seq)))
- (define (prime-sum? pair)
- (prime? (+ (first pair) (second pair))))
- (define (make-pair-sum pair)
- (list (first pair) (second pair) (+ (first pair) (second pair))))
- (define (unique-pairs n)
- (flatmap (lambda (i)
- (map (lambda (j) (list i j))
- (enumerate-interval 1 (sub1 i))))
- (enumerate-interval 1 n)))
- (unique-pairs 5)
- ;; '((2 1) (3 1) (3 2) (4 1) (4 2) (4 3) (5 1) (5 2) (5 3) (5 4))
- ;; A more Racketeering way of writing unique-pairs would be to use the built-in
- ;; list comprehensions:
- (define (racket-unique-pairs n)
- (for*/list ([i (in-range 1 (add1 n))]
- [j (in-range 1 i)])
- (list i j)))
- (racket-unique-pairs 5)
- ;; '((2 1) (3 1) (3 2) (4 1) (4 2) (4 3) (5 1) (5 2) (5 3) (5 4))
- (define (prime-sum-pairs n)
- (map make-pair-sum (filter prime-sum? (unique-pairs n))))
- (prime-sum-pairs 5)
- ;; '((2 1 3) (3 2 5) (4 1 5) (4 3 7) (5 2 7))
- ;;;;;;;;;;
- ;; 2.41 ;;
- ;;;;;;;;;;
- (define (sum-triples n s)
- (filter (lambda (triple) (= (apply + triple) s))
- (for*/list ([i (in-range 1 (add1 n))]
- [j (in-range 1 i)]
- [k (in-range 1 j)])
- (list k j i))))
- (sum-triples 9 12)
- ;; '((3 4 5) (2 4 6) (1 5 6) (2 3 7) (1 4 7) (1 3 8) (1 2 9))
- ;;;;;;;;;;
- ;; 2.42 ;;
- ;;;;;;;;;;
- (define (queens board-size)
- (define (queen-cols k)
- (if (zero? k)
- (list empty-board)
- (filter (lambda (positions) (safe? k positions))
- (flatmap (lambda (rest-of-queens)
- (map (lambda (new-row)
- (adjoin-position new-row k rest-of-queens))
- (enumerate-interval 1 board-size)))
- (queen-cols (sub1 k))))))
- (queen-cols board-size))
- ;; A queen is a list of row and column coordinates. A position is a list of queens.
- (define empty-board empty)
- (define (make-queen column row) (list column row))
- (define (col-coord queen) (first queen))
- (define (row-coord queen) (second queen))
- (define (adjoin-position column row position)
- (cons (make-queen column row) position))
- (define (safe? k position)
- ; #t if the first queen in position is safe from the other k - 1 queens
- (define (safe-from-one? queen1 queen2)
- (and (not (= (col-coord queen1)
- (col-coord queen2)))
- (not (= (row-coord queen1)
- (row-coord queen2)))
- (not (= (abs (- (col-coord queen1) ; different diagonals
- (col-coord queen2)))
- (abs (- (row-coord queen1)
- (row-coord queen2)))))))
- (andmap (lambda (q) (safe-from-one? (first position) q))
- (rest position)))
- (queens 3)
- ;; '()
- (queens 4)
- ;; '(((3 4) (1 3) (4 2) (2 1)) ((2 4) (4 3) (1 2) (3 1)))
- (queens 5)
- ;; '(((4 5) (2 4) (5 3) (3 2) (1 1))
- ;; ((3 5) (5 4) (2 3) (4 2) (1 1))
- ;; ((5 5) (3 4) (1 3) (4 2) (2 1))
- ;; ((4 5) (1 4) (3 3) (5 2) (2 1))
- ;; ((5 5) (2 4) (4 3) (1 2) (3 1))
- ;; ((1 5) (4 4) (2 3) (5 2) (3 1))
- ;; ((2 5) (5 4) (3 3) (1 2) (4 1))
- ;; ((1 5) (3 4) (5 3) (2 2) (4 1))
- ;; ((3 5) (1 4) (4 3) (2 2) (5 1))
- ;; ((2 5) (4 4) (1 3) (3 2) (5 1)))
- (queens 6)
- ;; '(((5 6) (3 5) (1 4) (6 3) (4 2) (2 1))
- ;; ((4 6) (1 5) (5 4) (2 3) (6 2) (3 1))
- ;; ((3 6) (6 5) (2 4) (5 3) (1 2) (4 1))
- ;; ((2 6) (4 5) (6 4) (1 3) (3 2) (5 1)))
- ;;;;;;;;;;
- ;; 2.43 ;;
- ;;;;;;;;;;
- (define (slow-queens board-size)
- (define (slow-queen-cols k)
- (if (zero? k)
- (list empty-board)
- (filter (lambda (positions) (safe? k positions))
- (flatmap (lambda (new-row)
- (map (lambda (rest-of-queens)
- (adjoin-position new-row k rest-of-queens))
- (slow-queen-cols (sub1 k))))
- (enumerate-interval 1 board-size)))))
- (slow-queen-cols board-size))
- ;; Interchanging the order of the loops causes the program to needlessly repeat
- ;; the call to queen-cols(k - 1) board-size times, for each new column k. But
- ;; it's even worse than that, because each one of those calls causes the program
- ;; to needlessly repeat all the recursive calls to queen-cols(j) for smaller j.
- ;; I'm not really sure what that does to the overall run time of queens(n). I
- ;; think it should be increased by a factor = 1 + n + n ^ 2 + ... + n ^ (n - 1)
- ;; which is on the order of n ^ (n - 1), but I couldn't get enough run times to
- ;; really test that.
- (for ([n (in-range 6 10)])
- (define fast-start-time (current-inexact-milliseconds))
- (define fast-num-solns (queens n))
- (define fast-time (- (current-inexact-milliseconds) fast-start-time))
- (define slow-start-time (current-inexact-milliseconds))
- (define slow-num-solns (slow-queens n))
- (define slow-time (- (current-inexact-milliseconds) slow-start-time))
- (printf "~a ~a ~a ~a ~a ~a ~n"
- n
- (length fast-num-solns)
- (round fast-time)
- (length slow-num-solns)
- (round slow-time)
- (round (/ slow-time fast-time))))
- ;; n solns1 fast-time solns2 slow-time ratio
- ;; 6 4 1.0 4 101.0 101.0
- ;; 7 40 3.0 40 1571.0 523.0
- ;; 8 92 15.0 92 32677.0 2252.0
- ;; 9 352 82.0 352 776164.0 9459.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement