- ;; ben piche
- ;; cs 287
- ;; homework 5
- ;;
- ;; question 1:
- ;; do exercise 3.22 on p. 266. make sure your dispatch procedure covers the following local procedures: front-ptr, rear-ptr, set-front-ptr!,
- ;; set-rear-ptr, empty-queue?, front-queue, insert-queue!, and delete-queue! as described on pp. 262-5.
- (define (make-queue)
- (let ((fptr '())
- (rptr '()))
- (define (front-ptr) fptr)
- (define (rear-ptr) rptr)
- (define (set-front-ptr! item) (set! fptr item))
- (define (set-rear-ptr! item) (set! rptr item))
- (define (empty-queue?) (null? (front-ptr)))
- (define (front-queue)
- (if (empty-queue?)
- (error "FRONT called with an empty queue" fptr)
- (car (front-ptr))))
- (define (insert-queue! item)
- (let ((new-pair (cons item '())))
- (cond ((empty-queue?)
- (set-front-ptr! new-pair)
- (set-rear-ptr! new-pair))
- (else
- (set-cdr! (rear-ptr) new-pair)
- (set-rear-ptr! new-pair)))))
- (define (delete-queue!)
- (cond ((empty-queue?)
- (error "DELETE! called with an empty queue" fptr))
- (else
- (set-front-ptr! (cdr (front-ptr))))))
- (define (dispatch m)
- (cond ((eq? m 'front-ptr) front-ptr)
- ((eq? m 'rear-ptr) rear-ptr)
- ((eq? m 'set-front-ptr!) set-front-ptr!)
- ((eq? m 'set-rear-ptr!) set-rear-ptr!)
- ((eq? m 'empty-queue?) empty-queue?)
- ((eq? m 'front-queue) front-queue)
- ((eq? m 'insert-queue!) insert-queue!)
- ((eq? m 'delete-queue!) delete-queue!)
- (else (error "ERROR" m))))
- dispatch))
- ;; question 2:
- ;; use make-queue from #1 above to generate all the binary strings of length n. we'll use lists of 1's and 0's to represent binary strings,
- ;; and we'll grow al the possible strings on the queue. define a procedure (allStrings n queue solutions) and call it with the following
- ;; parameters to generate all the strings of length 3:
- ;;
- ;; (define qu (make-queue))
- ;; ((qu 'insert-queue!) '())
- ;; (allStrings 3 qu '())
- (define (allStrings n q solutions)
- (if ((q 'empty-queue?))
- solutions
- (begin
- (if (= (length ((q 'front-queue))) n)
- (set! solutions (cons ((q 'front-queue)) solutions))
- (begin
- ((q 'insert-queue!) (cons 0 ((q 'front-queue))))
- ((q 'insert-queue!) (cons 1 ((q 'front-queue))))))
- ((q 'delete-queue!))
- (allStrings n q solutions))))
- ;; question 3: we will now use the queue-based strategy that worked for #2 above to solve the "missionaries and cannibals" problem.
- ;; the problem: three missionaries and three cannibals are on the left bank of a river and they want to cross the river to the right bank.
- ;; they have a boat but it can carry only two people at a time. all the missionaries and cannibals are able to row the boat. getting
- ;; everyone from one side to the other would be trivial except for one complication. if at any time the cannibals outnumber the missionaries
- ;; on a river bank the cannibals will eat the missionaries. although reducing the number of missionaries does simplify the problem, we will
- ;; not condone solutions that rely on anthropophagous activities. find all the possible solutions to this problem (there is more than one).
- ;;
- ;; represent your problem states with a procedure:
- ;;
- ;; (make-MC-state left right previous-state)
- ;;
- ;; where 'make-MC-state' returns a dispatch procedure. this dispatch procedure should be defined to return the following procedures defined
- ;; locally inside 'make-MC-state':
- ;;
- ;; ((s 'show))
- ;; ((s 'goal?))
- ;; ((s 'get-previous-state))
- ;; ((s 'find-totally-new-states) s)
- ;;
- ;; the queue processing for missionaries & cannibals works just like the queue in 'allStrings' in #2. each string in 'allStrings' was either
- ;; a solution string or a string that generated two new strings for the queue. in 'solveMC', each state is either the solution state, or a
- ;; state that might generate new states that could folow the current state in a move sequence. you will end up in an infinite loop if you
- ;; allow the same state to appear more than once in one move sequence. make sure you never add a state to a move sequence if that same state
- ;; can be found earlier (anywhere) in the chain of previous states. note that you can always examine all the states in a move sequence by
- ;; chaining back through all of the previous tates from the most recent 'MC-state'.
- (define (make-MC-state left right prev)
- (define (show) (list left right))
- (define (goal?) (equal? left '(#f 0 0)))
- (define (get-previous-state) prev)
- (define (num-miss lst) (caddr lst))
- (define (num-cann lst) (cadr lst))
- (define (isPrevSame? lst prev)
- (cond ((null? prev) #f)
- ((let ((Ls ((lst 'show)))(Ps ((prev 'show))))
- (and (equal? (caar Ls) (caar Ps)) (= (cadar Ls) (cadar Ps)) (= (caddar Ls) (caddar Ps))
- (equal? (caadr Ls) (caadr Ps)) (= (cadadr Ls) (cadadr Ps)) (= (car (cddadr Ls)) (car (cddadr Ps)))))
- #t)
- (else (isPrevSame? lst ((prev 'get-previous-state))))))
- (define (find-totally-new-states s)
- (define fromside (if (equal? (car left) #t) left right))
- (define toside (if (equal? (car left) #t) right left))
- (define (makenew nM nC)
- (if (equal? (car left) #t)
- (make-MC-state (list #f (- (cadr left) nC) (- (caddr left) nM)) (list #t (+ (cadr right) nC) (+ (caddr right) nM)) s)
- (make-MC-state (list #t (+ (cadr left) nC) (+ (caddr left) nM)) (list #f (- (cadr right) nC) (- (caddr right) nM)) s)))
- (let ((poss '()))
- (define (addifok lst)
- (if (and (equal? (isPrevSame? lst ((lst 'get-previous-state))) #f)
- (or (= (num-miss (car ((lst 'show)))) 0) (>= (num-miss (car ((lst 'show)))) (num-cann (car ((lst 'show))))))
- (or (= (num-miss (cadr ((lst 'show)))) 0) (>= (num-miss (cadr ((lst 'show)))) (num-cann (cadr ((lst 'show)))))))
- (set! poss (cons lst poss))))
- (begin
- (if (> (num-miss fromside) 1) (addifok (makenew 2 0)))
- (if (> (num-cann fromside) 1) (addifok (makenew 0 2)))
- (if (> (num-miss fromside) 0) (addifok (makenew 1 0)))
- (if (> (num-cann fromside) 0) (addifok (makenew 0 1)))
- (if (and (> (num-miss fromside) 0) (> (num-cann fromside) 0)) (addifok (makenew 1 1)))
- poss)))
- (define (dispatch m)
- (cond ((eq? m 'show) show)
- ((eq? m 'goal?) goal?)
- ((eq? m 'get-previous-state) get-previous-state)
- ((eq? m 'find-totally-new-states) find-totally-new-states)
- (else (error "ERROR" m))))
- dispatch)
- (define (solveMC q solutions)
- (if ((q 'empty-queue?))
- solutions
- (begin
- (if ((((q 'front-queue)) 'goal?))
- (set! solutions (cons ((q 'front-queue)) solutions))
- (map (lambda (x) ((q 'insert-queue!) x)) ((((q 'front-queue)) 'find-totally-new-states) ((q 'front-queue)))))
- ((q 'delete-queue!))
- (solveMC q solutions))))
- (define (seeSolutions lst)
- (define (recurse L ret)
- (if (equal? ((L 'get-previous-state)) '()) ret
- (begin (set! ret (cons ((L 'show)) ret)) (recurse ((L 'get-previous-state)) ret))))
- (map (lambda (x) (recurse x '())) lst))