Exercise 2.33 of SICP
Exercise 2.33: Fill in the missing expressions to complete the following definitions of some basic list-manipulation operations as accumulations:
(define (map p sequence) (accumulate (lambda (x y) <??>) nil sequence)) (define (append seq1 seq2) (accumulate cons <??> <??>)) (define (length sequence) (accumulate <??> 0 sequence))
(define (accumulate fn init-value items) (if (null? items) init-value (fn (car items) (accumulate fn init-value (cdr items))))) (define (map p sequence) (accumulate (lambda (x y) (cons (p x) y)) '() sequence)) (define (append seq1 seq2) (accumulate cons seq2 seq1)) (define (length seq) (accumulate (lambda (x y) (+ 1 y)) 0 seq))
I find it interesting how length is created by discarding the x in lambda thus discarding (car items).
Exercise 2.32 of SICP
Exercise 2.32: We can represent a set as a list of distinct elements, and we can represent the set of all subsets of the set as a list of lists. For example, if the set is (1 2 3), then the set of all subsets is (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3)). Complete the following definition of a procedure that generates the set of subsets of a set and give a clear explanation of why it works:
(define (subsets s)
(if (null? s)
(list nil)
(let ((rest (subsets (cdr s))))
(append rest (map <??> rest)))))
In order for me to understand what is going on here, I understand how powersets are constructed first and then derive this function.
This program wants to create what is called a powerset.
If S is a set of {a1,a2,a3}

The reasoning to construct a powerset is similar to the way the count change example is thought about.
Create a powerset for the cdr elements without using the car element, cons the car element with powerset of cdr elements. To the result append powerset of cdr elements.
When the arguments are an element and a set inject the element into every element of the set creating a new set. Append that result with the original powerset injected into.
P{
}
{
}
P{a1}
(append (inject a1 P{
}) P{
})
{{a1}
}
P{a1 a2}
(append (inject a1 P{a2}) P{a2})
(append {{a1 a2} {a1}} P{a2})
{{a1 a2} {a1} {a2}
}
P{a1 a2 a3}
(append (inject a1 P{a2 a3}) P{a2 a3})
(append (inject a1 (apend (inject a2 P{a3}) P{3}))
(append (inject a2 P{a3}) P{a3}))
(append (inject a1 (append (inject a2 {{a3}
}) {{a3}
}))
(append (inject a2 {{a3}
}) {{a3}
}))
(append (inject a1 (append {{a3 a2} {a2}} {{a3}
}))
(append (inject a2 {{a3}
}) {{a3}
}))
(append (inject a1 {{a3 a2} {a2} {a3}
})
(append {{a3 a2} {a2}} {{a3}
}))
(append {{a3 a2 a1 } {a2 a1} {a3 a1} {a1}}
(append {{a3 a2} {a2}} {{a3}
}))
(append {{a3 a2 a1 } {a2 a1} {a3 a1} {a1}}
{{a3 a2} {a2} {a3}
})
{{a3 a2 a1} {a2 a1} {a3 a1} {a1} {a3 a2} {a2} {a3}
}
Here is the process above in code:
(define (powerset ss) (if (null? ss) (list '()) (append (inject (car ss) (powerset (cdr ss))) (powerset (cdr ss))))) (define (inject s ss) (map (lambda (elem) (cons s elem)) ss))
Finally:
(define (subsets s) (if (null? s) (list '()) (let ((rest (subsets (cdr s)))) (append rest (map (lambda (elem) (cons (car s) elem)) rest)))))
It's worth noticing that because of the let expression (subsets (cdr s)) is only called once, as opposed to twice in my earlier derivation.
Exercise 2.31 of SICP
Exercise 2.31: Abstract your answer to exercise 2.30 to produce a procedure tree-map with the property that square-tree could be defined as
(define (square-tree tree) (tree-map square tree))
(define (tree-map fn tree) (map (lambda (sub-tree) (if (not (pair? sub-tree)) (fn sub-tree) (tree-map fn sub-tree))) tree)) (define (square-tree tree) (tree-map (lambda (x) (* x x)) tree))
> (define t (list 1
(list 2 (list 3 4) 5)
(list 6 7)))
> t
(1 (2 (3 4) 5) (6 7))
> (square-tree t)
(1 (4 (9 16) 25) (36 49))
Exercise 2.30 of SICP
Exercise 2.30: Define a procedure square-tree analogous to the square-list procedure of exercise 2.21. That is, square-list should behave as follows:
(square-tree
(list 1
(list 2 (list 3 4) 5)
(list 6 7)))
(1 (4 (9 16) 25) (36 49))
Define square-tree both directly (i.e., without using any higher-order procedures) and also by using map and recursion.
(define (map proc items) (if (null? items) '() (cons (proc (car items)) (map proc (cdr items))))) (define (square x) (* x x)) (define (square-tree tree) (cond ((null? tree) '()) ((not (pair? tree)) (square tree)) (else (cons (square-tree (car tree)) (square-tree (cdr tree)))))) (define (map-square-tree tree) (map (lambda (sub-tree) (if (not (pair? sub-tree)) (square sub-tree) (map-square-tree sub-tree))) tree))
> (define t (list 1
(list 2 (list 3 4) 5)
(list 6 7)))
> t
(1 (2 (3 4) 5) (6 7))
> (map-square-tree t)
(1 (4 (9 16) 25) (36 49))
> (square-tree t)
(1 (4 (9 16) 25) (36 49))
Exercise 2.29 of SICP
Exercise 2.29: A binary mobile consists of two branches, a left branch and a right branch. Each branch is a rod of a certain length, from which hangs either a weight or another binary mobile. We can represent a binary mobile using compound data by constructing it from two branches (for example, using list):
(define (make-mobile left right) (list left right))
A branch is constructed from a length (which must be a number) together with a structure, which may be either a number (representing a simple weight) or another mobile:
(define (make-branch length structure) (list length structure))
a. Write the corresponding selectors left-branch and right-branch, which return the branches of a mobile, and branch-length and branch-structure, which return the components of a branch.
(define (make-mobile left right) (list left right)) (define (left-branch mobile) (if (null? mobile) '() (car mobile))) (define (right-branch mobile) (if (null? mobile) '() (car (cdr mobile)))) (define (make-branch length structure) (list length structure)) (define (branch-length branch) (if (null? branch) 0 (car branch))) (define (branch-structure branch) (if (null? branch) 0 (car (cdr branch))))
b. Using your selectors, define a procedure total-weight that returns the total weight of a mobile.
(define (total-weight mobile) (define (weight? x) (not (pair? x))) (define (weight-of-branch branch) (let ((struct (branch-structure branch))) (if (weight? struct) struct (total-weight struct)))) (let ((lbranch (left-branch mobile)) (rbranch (right-branch mobile))) (cond ((null? mobile) 0) (else (+ (weight-of-branch lbranch) (weight-of-branch rbranch))))))
> (define m (make-mobile (make-branch 1 2) (make-branch 3 4)))
> (total-weight m)
6
> (define n (make-mobile (make-branch 1 (make-mobile (make-branch 1 2) (make-bra
nch 3 4))) (make-branch 2 (make-mobile (make-branch 2 2) (make-branch 3 1)))))
> (total-weight n)
9
c. A mobile is said to be balanced if the torque applied by its top-left branch is equal to that applied by its top-right branch (that is, if the length of the left rod multiplied by the weight hanging from that rod is equal to the corresponding product for the right side) and if each of the submobiles hanging off its branches is balanced. Design a predicate that tests whether a binary mobile is balanced.
(define (torque-balanced? mobile) (define (weight? x) (not (pair? x))) (define (torque branch) (let ((struct (branch-structure branch))) (* (branch-length branch) (if (weight? struct) struct (+ (torque (left-branch struct)) (torque (right-branch struct))))))) (if (null? mobile) #t (= (torque (left-branch mobile)) (torque (right-branch mobile)))))
> (define m (make-mobile (make-branch 1 2) (make-branch 2 1)))
> (torque-balanced? m)
#t
> (torque-balanced? n)
#t
> (define m (make-mobile (make-branch 1 2) (make-branch 2 2)))
> (torque-balanced? m)
#f
d. Suppose we change the representation of mobiles so that the constructors are
(define (make-mobile left right) (cons left right)) (define (make-branch length structure) (cons length structure))
How much do you need to change your programs to convert to the new representation?
Only two changes are needed to selectors of the right side elements because (cdr (list 1 (list 2))) returns ((2)). However the nested list problem doesn't happen with dotted pairs.
(define (right-branch mobile) (if (null? mobile) '() (cdr mobile)))
(define (branch-structure branch) (if (null? branch) 0 (cdr branch)))
Exercise 2.28 of SICP
Exercise 2.28: Write a procedure fringe that takes as argument a tree (represented as a list) and returns a list whose elements are all the leaves of the tree arranged in left-to-right order. For example,
(define x (list (list 1 2) (list 3 4))) (fringe x) (1 2 3 4) (fringe (list x x)) (1 2 3 4 1 2 3 4)
(define (fringe x) (cond ((null? x) '()) ((not (pair? x)) (list x)) (else (append (fringe (car x)) (fringe (cdr x))))))
> (define x (list (list 1 2) (list 3 4)))
> (fringe x)
(1 2 3 4)
> (fringe (list x x))
(1 2 3 4 1 2 3 4)
Exercise 2.27 of SICP
Exercise 2.27: Modify your reverse procedure of exercise 2.18 to produce a deep-reverse procedure that takes a list as argument and returns as its value the list with its elements reversed and with all sublists deep-reversed as well. For example,
(define x (list (list 1 2) (list 3 4))) x ((1 2) (3 4)) (reverse x) ((3 4) (1 2)) (deep-reverse x) ((4 3) (2 1))
(define (deep-reverse x) (cond ((null? x) '()) ((not (pair? x)) (list x)) ((not (pair? (car x))) (append (deep-reverse (cdr x)) (list (car x)))) (else (append (deep-reverse (cdr x)) (list (deep-reverse (car x)))))))
> (define x (list (list 1 2) (list 3 4)))
> (deep-reverse x)
((4 3) (2 1))
> (define y (list (list (list 1 2)) (list 3 4)))
> y
(((1 2)) (3 4))
> (deep-reverse y)
((4 3) ((2 1)))
Exercise 2.26 of SICP
Exercise 2.26: Suppose we define x and y to be two lists:
(define x (list 1 2 3)) (define y (list 4 5 6))
What result is printed by the interpreter in response to evaluating each of the following expressions:
(append x y)
(1 2 3 4 5 6)
(cons x y)
((1 2 3) 4 5 6)
(list x y)
((1 2 3) (4 5 6))
Exercise 2.25 of SICP
Exercise 2.25: Give combinations of cars and cdrs that will pick 7 from each of the following lists:
(1 3 (5 7) 9) ((7)) (1 (2 (3 (4 (5 (6 7))))))
> (define a (list 1 3 (list 5 7) 9))
> (car (cdr (car (cdr (cdr a)))))
7
> (define a (list (list 7)))
> (car (car a))
7
> (define a (list 1 (list 2 (list 3 (list 4 (list 5 (list 6 7)))))))
> (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr a))))))))))))
7
Exercise 2.24 of SICP
Exercise 2.24: Suppose we evaluate the expression (list 1 (list 2 (list 3 4))). Give the result printed by the interpreter, the corresponding box-and-pointer structure, and the interpretation of this as a tree (as in figure 2.6).
(1 (2 (3 4)))
1 2 3 4 5 | [1 *]->[* /] | [2 *]->[* /] | [3 *]->[4 /] |