;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Problem 1 ;;;;;; ;;; ;;; An implementation playing the game-of-24 ;;; ;;; Author: Hongwei Xi ;;; CS Department, BU ;;; ;;; Jan 31, 2002 ;;; ;;;;;; ;;; we need the format package for displaying results (load-option 'format) ;;; this is an implementation of a generalized version of game-of-24 ;;; a card is a pair (number expression) ;;; an expression is a pair (priority string) (define nil ()) ;;; turining a number into a card (define (card-of-num n) (cons n (cons 3 (write-to-string n)))) ;;; obtaining the string representation of a card (define (string-of-card c) (cddr c)) ;;; forming string representation of an expression (define (exp-op opname priority exp1 exp2) (let ((str1 (if (>= (car exp1) priority) (cdr exp1) (string-append "(" (cdr exp1) ")"))) (str2 (if (> (car exp2) priority) (cdr exp2) (string-append "(" (cdr exp2) ")")))) (cons priority (string-append str1 opname str2)))) ;;; applying a given operation to cards x and y (define (card-op op opname priority x y) (cons (op (car x) (car y)) (exp-op opname priority (cdr x) (cdr y)))) ;;; applying allowed operations to cards x and y (define (card-ops x y) (define (aux x y) (let ((res (cons (card-op * "*" 2 x y) (cons (card-op - "-" 1 x y) (cons (card-op - "-" 1 y x) (cons (card-op + "+" 1 x y) ())))))) (if (or (zero? (car x)) (zero? (car y))) res (cons (card-op / "/" 2 x y) (cons (card-op / "/" 2 y x) res))))) (aux x y)) ;;; turn numbers into cards (define (cards-of-nums ns) (map card-of-num ns)) ;;; reverse append (define (rapp xs ys) (if (null? xs) ys (rapp (cdr xs) (cons (car xs) ys)))) ;;; play-game is a function that checks whether a list of given ;;; number can generate the number res following the rule of ;;; game-of-24 (define (play-game ns res) (define (show-solution c) (format #t "~A = ~A" (string-of-card c) res)) (define (main zs) (if (null? zs) (error "main: empty list") (if (null? (cdr zs)) (if (= (first (car zs)) res) (begin (show-solution(car zs)) #t) #f) (aux1 (first zs) nil (second zs) nil (cddr zs))))) (define (aux1 x xs y ys zs) (define (aux11 rs) (if (null? rs) (aux2 x xs y ys zs) (or (main (rapp xs (rapp ys (cons (car rs) zs)))) (aux11 (cdr rs))))) (aux11 (card-ops x y))) (define (aux2 x xs y ys zs) (if (null? zs) (and (not (null? ys)) (let ((zs1 (rapp ys (cons y nil)))) (aux1 (first zs1) (cons x xs) (second zs1) nil (cddr zs1)))) (aux1 x xs (car zs) (cons y ys) (cdr zs)))) (main (cards-of-nums ns))) ;;; play24 is the function that check if four given numbers are a good quad (define (play24 n1 n2 n3 n4) (if (play-game (list n1 n2 n3 n4) 24) 1 0)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Problem 2 ; (/ (+ 5 (+ 4 (- (2 (- 3 (+ 6 (/ 4 5))))))) (* 3 (* (- 6 2) (- 2 7)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Problem 3 - example that shows why new-if can't be used always instead of if. ; The problem with it is that new-if *always* causes its arguments to be ; evaluated, whereas if evaluates only the boolean condition and one of the ; remaining two, depending on what the condition evaluated to. ; In this examople, the problem is that the countdown doesn't stop, since ; (countdown (- n 1)) is evaluated always, regardles of whether (> n 0) is true ; or false. ; Note that new-if only *evaluates* all its arguments, but *does not return* ; all of them; it returns only one, depending on what the condition evaluated ; to. In that respect, new-if behaves like the original if. (define (new-if predicate? then-clause else-clause) (cond (predicate? then-clause) (else else-clause))) (define (countdown n) (new-if (> n 0) (countdown (- n 1)) 0 )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Problem 4 (define (triangle a b c) (and (> (+ a b) c) (> (+ a c) b) (> (+ b c) a)) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Problem 5; exact->inexact transforms an exact number (rational number with ; exact numerator and denominator) into a floating - point number; otherwise ; the result would be too hard to read -- see for yourself (define (cuberoot x) (exact->inexact (cuber x 1 0.1)) ) (define (cuber x y eps) (if (< (abs (- (approx x y) y)) eps) (approx x y) (cuber x (approx x y) eps) )) (define (approx x y) (/ (+ (/ x (* y y)) (* 2 y)) 3) ) ;;;;;;;;;;;;;;;;;;;; ;;; ;;; exercise 6 ;;; ;;;;;;;;;;;;;;;;;;;; ;;; The first solution (define true #t) (define false #f) (define (is-square? n) ;;; j is to be the square of i (define (aux i j) (cond ((< n j) false) ((= n j) true) (else (aux (1+ i) (+ j i i 1))))) (aux 0 0)) (define (find-it) ;;; j is to be the cube of i (define (aux i j) (if (is-square? (- j 2)) (- j 1) ;;; (i+1)^3 = i^3 + 3 i^2 + 3 i + 1 (aux (1+ i) (+ j (* 3 i i) i i i 1)))) (aux 0 0)) ;;; ;;; how to run it: ;;; (find-it) returns the answer 26 ;;; another solution to exercise 6, which is easier to understand (define (ncheck n) (if (and (n-1check n) (n+1check n)) n (ncheck (+ n 1)))) (define (n-1check n) (xcheck 0 n)) (define (n+1check n) (ycheck 0 n)) (define (xcheck x n) (cond ((> (* x x) (- n 1)) #f) ((= (* x x) (- n 1)) #t) (else (xcheck (1+ x) n)))) (define (ycheck y n) (cond ((> (* y y y) (1+ n)) #f) ((= (* y y y) (1+ n)) #t) (else (ycheck (1+ y) n)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Problem 6 (define (issquare x i) (cond ((= (* i i) x) #t) ((>= i x) #f) (else (issquare x (+ i 1))) )) (define (iscube x i) (cond ((= (* i i i) x) #t) ((>= i x) #f) (else (iscube x (+ i 1))) )) (define (lookfornumber n) (if (and (issquare (- n 1) 1) (iscube (+ n 1) 1)) n (lookfornumber (+ n 1)) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Problem 7 (define f (lambda (x) (cond ((< x 101) (f (f (+ x 11)))) (else (- x 10))))) (define g (lambda (x) (cond ((< x 101) (+ (g (f (+ x 11))) (g (+ x 11)) 1) ) (else 1)))) ;;;;;;;;;;;;;;;;;;;; ;;; ;;; exercise 7 ;;; ;;;;;;;;;;;;;;;;;;;; ; this solution is the same as the previously one (define (f91 x) (if (< x 101) (f91 (f91 (+ x 11))) (- x 10))) (define (g91 x) (if (< x 101) (+ 1 (g91 (+ x 11)) (g91 (f91 (+ x 11)))) 1)) ;;; ;;; (g91 x) returns the number of calls to f91 when (f91 x) ;;; is computed ;;; ;;;;;;;;;;;;;;;; ;;; ;;; end of Assignment 1 ;;; ;;;;;;;;;;;;;;;;