;; SICP - Ch. 2, Exercise (4)
;; @see 2L98t5
(define (square x)
(* x x))
(define (accumulate op init seq)
(if (null? seq)
init
(op (car seq)
(accumulate op init (cdr seq)))))
;; 2.33: Fill in the missing expressions to complete
;; the following definitions of some basic list-manipulation
;; operations as accumulations:
(define (my-map proc seq)
(accumulate (lambda (x y) (cons (proc x) y)) '() seq))
(define (my-append seq1 seq2)
(accumulate cons seq2 seq1))
(define (my-length seq)
(accumulate (lambda (_ y) (+ 1 y)) 0 seq))
(define x (list 1 2 3 4))
(define y (list 5 6 7))
(format #t "~%~A" (my-map square x))
(format #t "~%~A" (my-append x y))
(format #t "~%~A" (my-length x))
;; 2.34: Fill in the following template to produce a procedure
;; that evaluates a polynomial using Horner’s rule.
(define (horner-eval x coefficient-sequence)
(accumulate (lambda (this-coeff higher-terms) (+ this-coeff (* x higher-terms)))
0
coefficient-sequence))
;; 1 + 3x + 5x^3 + x^5 at x = 2
(format #t "~%~A" (horner-eval 2 (list 1 3 0 5 0 1)))
;; 2.35: Redefine count-leaves as an accumulation:
(define (count-leaves t)
(accumulate + 0 (map (lambda (x) (if (pair? x) (count-leaves x) 1)) t)))
(define x (cons (list 1 2) (list 3 4)))
(format #t "~%~A" (count-leaves x))
(format #t "~%~A" (count-leaves (list x x)))
;; 2.36: Fill in the missing expressions in the following definition
;; of accumulate-n:
(define (accumulate-n op init seqs)
(if (null? (car seqs))
'()
(cons (accumulate op init (map car seqs))
(accumulate-n op init (map cdr seqs)))))
(define x (list (list 1 2 3)
(list 4 5 6)
(list 7 8 9)
(list 10 11 12)))
(format #t "~%~A" (accumulate-n + 0 x))
;; 2.37: Fill in the missing expressions in the following procedures
;; for computing the other matrix operations.
(define (dot-product v w)
(accumulate + 0 (map * v w)))
(define (matrix-*-vector m v)
(map (lambda (w) (dot-product v w)) m))
(define (transpose m)
(accumulate-n cons '() m))
(define (matrix-*-matrix m n)
(let ((cols (transpose n)))
(map (lambda (row) (matrix-*-vector cols row)) m)))
(define x (list (list 1 2 3 4)
(list 4 5 6 6)
(list 6 7 8 9)))
(format #t "~%~A" (matrix-*-vector x (list 1 1 1 1)))
(format #t "~%~A" (transpose x))
(format #t "~%~A" (matrix-*-matrix x (transpose x)))
;; 2.38: The accumulate procedure is also known as fold-right, because
;; it combines the first element of the sequence with the result of
;; combining all the elements to the right. There is also a fold-left,
;; which is similar to fold-right, except it combines elements working
;; in the opposite direction:
(define (fold-right op init seq)
(accumulate op init seq))
(define (fold-left op init seq)
(define (iter result rest)
(if (null? rest)
result
(iter (op result (car rest))
(cdr rest))))
(iter init seq))
(define x (list 1 2 3))
(format #t "~%~A" (fold-right / 1 x))
(format #t "~%~A" (fold-left / 1 x))
(format #t "~%~A" (fold-right list '() x))
(format #t "~%~A" (fold-left list '() x))
;; 2.39: Complete the following definitions of reverse (Exercise 2.18)
;; in terms of fold-right and fold-left from Exercise 2.38:
(define (my-reverse-r seq)
(fold-right (lambda (x y) (append y (list x))) '() seq))
(define (my-reverse-l seq)
(fold-left (lambda (x y) (cons y x)) '() seq))
(format #t "~%~A" (my-reverse-r x))
(format #t "~%~A" (my-reverse-l x))