Chapter 2, Building Abstractions with Data

Section - 2.2 - Hierarchical Data and the Closure Property

Exercise 2.29


(a)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#lang sicp

(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))
)

(b)

1
2
3
4
5
6
7
8
9
10
(define (total-weight mobile)
  (cond ((null? mobile) 0)
        ((not (pair? mobile)) mobile)
        (else (+
                 (total-weight (branch-structure (left-branch mobile)))
                 (total-weight (branch-structure (right-branch mobile)))
              )
        )
  )
)

Example/Test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
> (define mob
    (make-mobile
       (make-branch
             100
             (make-mobile
                   (make-branch 100 1)
                   (make-branch 
                         100 
                         (make-mobile 
                               (make-branch 100 2) 
                               (make-branch 100 3)
                         )
                   )
             )
       )
       (make-branch
             100
             (make-mobile
                   (make-branch 
                         100 
                         (make-mobile 
                               (make-branch 100 4) 
                               (make-branch 100 5)
                         )
                   )
                   (make-branch 100 6)                         
             )
       )
    )
 )
                         
> (total-weight mob)
21

> (total-weight '())
0

(c)

I attempted in writing procedure that visits each branch of the mobile only once.

To do that a procedure chk-balance is written which returns weight of the mobile if mobile is balanced else it returns a negative number. As can be seen in code this helps in avoiding multiple visits to each branch.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(define (balanced? m)  
  (define (chk-balance mobile)
     (cond ((null? mobile) 0)
        ((not (pair? mobile)) mobile)
        (else
              (let (
                     (left-wt (chk-balance (branch-structure (left-branch mobile))))
                     (right-wt (chk-balance (branch-structure (right-branch mobile))))
                   )            
                   (if (and
                           (>= left-wt 0)
                           (>= right-wt 0)
                           (=
                              (* left-wt (branch-length (left-branch mobile)))
                              (* right-wt (branch-length (right-branch mobile)))
                           )
                       )    
                       (+ left-wt right-wt)
                       -1
                   )    
              )
        )
     )    
  )
  (>= (chk-balance m) 0)
)

Example/Test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
> (define mob
    (make-mobile
       (make-branch
             100
             (make-mobile
                      (make-branch 100 1)
                      (make-branch 100 (make-mobile (make-branch 100 2) (make-branch 100 3)))
             )
       )
       (make-branch
             100
             (make-mobile
                      (make-branch 100 (make-mobile (make-branch 100 4) (make-branch 100 5)))
                      (make-branch 100 6)                         
             )
       )
  )
)
> (balanced? mob)
#f
> (define mob
    (make-mobile
       (make-branch
             100
             (make-mobile
                      (make-branch 100 16)
                      (make-branch 100 (make-mobile (make-branch 100 8) (make-branch 100 8)))
             )
       )
       (make-branch
             100
             (make-mobile
                      (make-branch 100 (make-mobile (make-branch 100 8) (make-branch 100 8)))
                      (make-branch 100 16)                         
             )
       )
  )
)
> (balanced? mob)
#t

(d)

The modified constructors will cause changes only in selectors right-branch and branch-structure.