2.29 Exercise 2.29
First of all, writing the selectors left-branch and right-branch is trivial,
as well as branch-length and branch-structure:
(define right-branch cadr) |
(define branch-length car) |
(define branch-structure cadr) |
Finding the total weight of a branch is just a matter of summing the weights of the
left and right branches recursively. We can do that using two procedures, total-weight
and weigh-branch, both of which call each other:
(define (weigh-branch branch) | (let ((s (branch-structure branch))) | (if (not (list? s)) s | (total-weight s)))) |
|
(define (total-weight mobile) | (+ (weigh-branch (left-branch mobile)) (weigh-branch (right-branch mobile)))) |
|
To determine if a mobile is balanced, we can follow the definition of a balanced mobile
and define a recursive procedure that tests whether two branches have equal torque (where
torque is computed by an inner procedure) and, if so, recursively checks if the
mobiles rooted at each branch are balanced:
(define (is-mobile-balanced? mobile) | (define (torque branch) | (* (branch-length branch) (weigh-branch branch))) | (define (are-submobiles-balanced? branch) | (let ((s (branch-structure branch))) | | (if (not (list? s)) #t | (is-mobile-balanced? s)))) | (let ((left (left-branch mobile)) | (right (right-branch mobile))) | (if (not (= (torque left) (torque right))) #f | (and | (are-submobiles-balanced? left) | (are-submobiles-balanced? right))))) |
|
Supposing that we changed the representation of mobiles to use cons cells instead of
lists, we would only need to change the selectors right-branch and branch-structure
to use cdr instead of cadr, and also change the list? checks to pair? checks.
(We could also use pair? checks in this implementation, since lists are pairs, but I believe
it is better to use the more restrictive selector).