sicp-solutions/ex-2.29.scm

60 lines
2.2 KiB
Scheme

#lang sicp
(define (make-mobile left right)
(list left right))
; a. part 1
(define (left-branch mobile)
(car mobile))
(define (right-branch mobile)
(cadr mobile))
(define (make-branch length structure)
(list length structure))
; a. part 2
(define (branch-length branch)
(car branch))
(define (branch-structure branch)
(cadr branch))
; b
(define (total-weight mobile)
(if (number? mobile)
mobile
(+ (total-weight (branch-structure (left-branch mobile)))
(total-weight (branch-structure (right-branch mobile))))))
; c, with O(n) complexity, because the basic algorithm would
; recalculate weights of lower level submobiles, each node is
; calculated h times, where h is the number of it's ancestors
; for a typical mobile, this would cause the complexity to be
; O(log(n) * n)
(define (mobile-balanced? mobile)
; this returns a pair, a bool describing whether the mobile
; is balanced, and a number, describing the total weight of
; the mobile
(define (balanced-aux mobile)
(if (number? mobile)
(cons #t mobile)
(let* ((left-submobile (branch-structure (left-branch mobile)))
(right-submobile (branch-structure (right-branch mobile)))
(len-left (branch-length (left-branch mobile)))
(len-right (branch-length (right-branch mobile)))
(bal-aux-left (balanced-aux left-submobile))
(bal-aux-right (balanced-aux right-submobile))
(balanced-left? (car bal-aux-left))
(balanced-right? (car bal-aux-right))
(weight-left (cdr bal-aux-left))
(weight-right (cdr bal-aux-right)))
(cons (and balanced-left?
balanced-right?
(= (* weight-left len-left)
(* weight-right len-right)))
(+ weight-left weight-right)))))
(car (balanced-aux mobile)))
; d. The way we wrote the code so far, we've managed to
; cleanly separate the internals of the mobile and branch
; structures from the code which uses them, so the only thing
; that needs to be changed is the selectors. In this case in
; particular, we only need to change the right-branch, and
; branch-structure selectors, by changing the cadr into a cdr