<< Previous exercise (2.28) | Index | Next exercise (2.30) >>

; balanced? predicate (define (balanced? m) (define (total-weight m) (define (branch-weight b) (let ((s (branch-structure b))) (if (mobile? s) (total-weight s) s))) (let* ((l (left-branch m)) (r (right-branch m)) (lw (branch-weight l)) (rw (branch-weight r))) (if (or (< lw 0) (< rw 0)) -1 (let ((lt (* (branch-length l) lw)) (rt (* (branch-length r) rw))) (if (= lt rt) (+ lw rw) -1))))) (> (total-weight m) -1))

Another form of (balanced? mobile)

```
(define (balanced? mobile)
(define (torque branch)
;find torque on this particular branch
(if (is-mobile? (branch-struct branch))
(* (branch-len branch)
(total-weight (branch-struct branch)))
(* (branch-len branch)
(branch-struct branch))))
;nested AND for each branch pair
(and (= (torque (left-branch mobile))
(torque (right-branch mobile)))
;if more branches, repeat balanced? - if a leaf is
;reached, return #t
(if (is-mobile? (branch-struct (left-branch mobile)))
(balanced? (branch-struct (left-branch mobile)))
#t)
(if (is-mobile? (branch-struct (right-branch mobile)))
(balanced? (branch-struct (right-branch mobile)))
#t)))
```

My balanced solution.

(define (make-mobile left right) (list left right)) (define (make-branch length structure) (list length structure)) (define (left-branch mobile) (car mobile)) (define (right-branch mobile) (car (cdr mobile))) (define (branch-length branch) (car branch)) (define (branch-structure branch) (car (cdr branch))) (define (left-structure mobile) ((compose branch-structure left-branch) mobile)) (define (right-structure mobile) ((compose branch-structure left-branch) mobile)) (define mobile? list?) (define (struct-eval struct m w) (if (mobile? struct) (m struct) (w struct))) (define (branch-weight branch) (define (mobile-structure) (lambda(mobile) (mobile-weight mobile))) (define (weight-structure) (lambda(weight) weight)) (struct-eval (branch-structure branch) (mobile-structure) (weight-structure))) (define (mobile-weight mobile) (+ (branch-weight (left-branch mobile)) (branch-weight (right-branch mobile)))) (define (branches-balance? left right) (= (branch-torque left) (branch-torque right))) (define (branch-torque branch) (* (branch-length branch) (branch-weight branch))) (define (mobile-balanced? mobile) (define (mobile-structure) (lambda(mobile) (mobile-balanced? mobile))) (define (weight-structure) (lambda(weight) #t)) (define (try-submobile? struct) (struct-eval struct (mobile-structure) (weight-structure))) (and (branches-balance? (left-branch mobile) (right-branch mobile)) ((compose try-submobile? left-structure) mobile) ((compose try-submobile? right-structure) mobile)))

A mobile is a structure. A simple weight is also a structure.

(define (make-mobile left right) (list left right)) (define (make-branch length structure) (list length structure)) (define (left-branch mobile) (car mobile)) (define (right-branch mobile) (cadr mobile)) (define (branch-length branch) (car branch)) (define (branch-structure branch) (cadr branch)) (define simple-weight? number?) (define (total-weight structure) (if (simple-weight? structure) structure (+ (total-weight (branch-structure (left-branch structure))) (total-weight (branch-structure (right-branch structure)))))) (define (balanced? structure) (define (torque branch) (* (branch-length branch) (total-weight (branch-structure branch)))) (if (simple-weight? structure) #t (let ((left (left-branch structure)) (right (right-branch structure))) (and (eq? (torque left) (torque right)) (balanced? (branch-structure left)) (balanced? (branch-structure right)))))) ; example (define m1 (make-mobile (make-branch 1 2) (make-branch 2 1))) (define m2 (make-mobile (make-branch 3 1) (make-branch 1 m1))) (balanced? m2) ;#true

My "balanced?" solution (takes advantage of the "or" predicate short-circuiting):

```
(define (balanced? mobile)
(let ((branch-torque (lambda (branch)
(* (branch-length branch)
(if (pair? (branch-structure branch))
(total-weight (branch-structure branch))
(branch-structure branch)))))
(branch-is-balanced? (lambda (branch)
(or (not (pair? (branch-structure branch)))
(balanced? (branch-structure branch))))))
(and (= (branch-torque (left-branch mobile))
(branch-torque (right-branch mobile)))
(branch-is-balanced? (left-branch mobile))
(branch-is-balanced? (right-branch mobile)))))
```

Someone delete this if I've made a mistake, but I think this is a correct and relatively simple `balanced?` predicate. It also has the benefit of being completely neutral with regards to the implementation of `mobile` and `branch`.

```
(define (balanced? mobile)
(define (torque branch)
(if (not (pair? (branch-structure branch)))
(* (branch-length branch) (branch-structure branch))
(- (torque (left-branch (branch-structure branch)))
(torque (right-branch (branch-structure branch))))))
(= (torque (left-branch mobile)) (torque (right-branch mobile))))
```

Damien in the example bellow your solution returns #f, but this mobile is balanced. The solution you proposed assign torque zero to the left branch, but it's torque is 2.

;; 1 | 2 ;; +-----+----+ 1 ;; 1 | 1 ;; +---+---+ ;; 1 1

Use the same recursion over the construction of the mobile for defining the function 'total-weight' as well as the predicate 'balanced?'. Take advantage of the fact that a variable has no type. The variable 'm' can in different calls take as a value a mobile, a branch or a number or empty list.

(define (make-mobile left right) (list left right)) (define (left-branch mobile) (car mobile)) (define (right-branch mobile) (car (cdr mobile))) (define (make-branch length structure) (list length structure)) (define (branch-length branch) (car branch)) (define (branch-structure branch) (car (cdr branch))) (define (total-weight m) (cond ((null? m) 0) ((not (pair? m)) m) (else (+ (total-weight (branch-structure (left-branch m))) (total-weight (branch-structure (right-branch m))))))) ;;Example m1 (define m1 (make-mobile (make-branch 4 6) (make-branch 5 (make-mobile (make-branch 3 7) (make-branch 9 8))))) ;; | ;; 4 | 5 ;; +----+-----+ ;; 6 3 | 9 ;; +---+---------+ ;; 7 8 ;; ;; (total-weight m1) ;; Value: 21 (define (balanced? m) (cond ((null? m) #t) ((not (pair? m)) #t) (else (and (= (* (branch-length (left-branch m)) (total-weight (branch-structure (left-branch m)))) (* (branch-length (right-branch m)) (total-weight (branch-structure (right-branch m))))) (balanced? (branch-structure (left-branch m))) (balanced? (branch-structure (right-branch m))))))) ;;Example m2 (define m2 (make-mobile (make-branch 4 6) (make-branch 2 (make-mobile (make-branch 5 8) (make-branch 10 4))))) ;; | ;; 4 | 2 ;; +----+--+ ;; 6 5 | 10 ;; +-----+----------+ ;; 8 4 ;; ;; balanced? m2) ;; Value: #t ;; (balanced? m1) ;; Value: #f

jz