home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d524
/
kamin.lha
/
Kamin
/
src.lzh
/
code.smt
< prev
next >
Wrap
Text File
|
1991-06-28
|
23KB
|
678 lines
; Code from previous chapters
(define +1 (x) (+ x 1))
(define or (x y) (if x x y))
(define and (x y) (if x y x))
(define not (x) (if x false true))
(define <> (x y) (not (= x y)))
(define <= (x y) (or (< x y) (= x y)))
(define divides (n x) (= (* n (/ x n)) x))
(define mod (n m) (- n (* m (/ n m))))
(define gcd (i j)
(if (> i j) (gcd j i)
(if (divides i j) i (gcd (mod j i) i))))
(define abs (x) (if (< x 0) (- 0 x) x))
; Section 7.1.1
(class FinancialHistory Object
(cashOnHand incomes expenditures)
(define initFinancialHistory (amount)
(begin
(set cashOnHand amount)
(set incomes (mkDictionary))
(set expenditures (mkDictionary))
self))
(define receive:from: (amount source)
(begin
(at:put: incomes source (+ (totalReceivedFrom: self source) amount))
(set cashOnHand (+ cashOnHand amount))))
(define spend:for: (amount reason)
(begin
(at:put: expenditures reason (+ (totalSpentFor: self reason) amount))
(set cashOnHand (- cashOnHand amount))))
(define cashOnHand () cashOnHand)
(define totalReceivedFrom: (source)
(if (includesKey: incomes source)
(at: incomes source)
0))
(define totalSpentFor: (reason)
(if (includesKey: expenditures reason)
(at: expenditures reason)
0))
)
(define mkFinancialHistory (amount)
(initFinancialHistory (new FinancialHistory) amount))
; Test cases for FinancialHistory moved to after Collection hierarchy
(class DeductibleHistory FinancialHistory
(deductible)
(define initDeductibleHistory (amount)
(begin
(initFinancialHistory self amount)
(set deductible 0)
self))
(define spend:Deduct: (amount reason)
(begin
(spend:for: self amount reason)
(set deductible (+ deductible amount))))
(define spend:for:deduct: (amount reason deduction)
(begin
(spend:for: self amount reason)
(set deductible (+ deductible deduction))))
(define totalDeductions () deductible))
(define mkDeductibleHistory (amount)
(initDeductibleHistory (new DeductibleHistory) amount))
; Test cases for DeductibleHistory moved to after Collection hierarchy
; Section 7.1.5
(set false 0)
(set true 1)
(define isNil (x) (= x #nil))
(define notNil (x) (<> x #nil))
(class Collection Object
() ; abstract class
(define first () #subclassResponsibility)
(define next () #subclassResponsibility)
(define add: (item) #subclassResponsibility)
(define size ()
(begin
(set tempitem (first self))
(set tempsize 0)
(while (notNil tempitem)
(begin
(set tempsize (+1 tempsize))
(set tempitem (next self))))
tempsize))
(define isEmpty () (isNil (first self)))
(define includes: (item)
(begin
(set tempitem (first self))
(set found false)
(while (and (notNil tempitem) (not found))
(if (= tempitem item)
(set found true)
(set tempitem (next self))))
found))
)
(class Set Collection
(members) ; list of elements
(define initSet () (begin (set members (mkList)) self))
(define first () (first members))
(define next () (next members))
(define add: (item)
(if (includes: members item) self (add: members item)))
)
(define mkSet () (initSet (new Set)))
;
(class KeyedCollection Collection
() ; abstract class
(define at:put: (key value) #subclassResponsibility)
(define currentKey () #subclassResponsibility)
(define at: (key)
(begin
(set tempvalue (first self))
(set found false)
(while (and (notNil tempvalue) (not found))
(if (= key (currentKey self))
(set found true)
(set tempvalue (next self))))
tempvalue)) ; note: nil if key out of range
(define includesKey: (key)
(notNil (at: self key)))
(define indexOf: (value)
(begin
(set tempvalue (first self))
(set found false)
(while (and (notNil tempvalue) (not found))
(if (= value tempvalue)
(set found true)
(set tempvalue (next self))))
(if (isNil tempvalue) #nil (currentKey self))))
)
;
(class Association Object
(fst snd)
(define initAssociation (x y) (begin (set fst x) (set snd y) self))
(define fst () fst)
(define snd () snd)
(define fst: (x) (set fst x))
(define snd: (y) (set snd y))
)
;
(define mkAssociation (a b) (initAssociation (new Association) a b))
(class Dictionary KeyedCollection
(table currentKey)
(define initDictionary ()
(begin (set table (mkList)) self))
(define currentKey () currentKey)
(define first ()
(if (isEmpty table) #nil
(begin
(set tempassoc (first table))
(set currentKey (fst tempassoc))
(snd tempassoc))))
(define next ()
(begin
(set tempassoc (next table))
(if (isNil tempassoc) #nil
(begin
(set currentKey (fst tempassoc))
(snd tempassoc)))))
(define at:put: (key value)
(begin
(set tempassoc (associationAt: self key))
(if (isNil tempassoc)
(add: table (mkAssociation key value))
(snd: tempassoc value))))
(define associationAt: (key)
(begin
(set temptable table)
(set found false)
(while (not (or (isEmpty temptable) found))
(if (= (fst (car temptable)) key)
(set found true)
(set temptable (cdr temptable))))
(if found (car temptable) #nil)))
)
(define mkDictionary () (initDictionary (new Dictionary)))
;
(class SequenceableCollection KeyedCollection
() ; abstract class
(define firstKey () #subclassResponsibility)
(define lastKey () #subclassResponsibility)
(define last () (at: self (lastKey self)))
(define at: (index)
(begin
(set iterations (- index (firstKey self)))
(set result (first self))
(while (> iterations 0)
(begin
(set result (next self))
(set iterations (- iterations 1))))
result))
)
(class List SequenceableCollection
(car cdr currentKey currentCell)
(define car () car)
(define cdr () cdr)
(define initList ()
(begin (set car #nil) self))
(define add: (item)
(begin
(set temp (new List))
(car: temp car)
(cdr: temp cdr)
(set cdr temp)
(set car item)))
(define car: (x) (set car x))
(define cdr: (x) (set cdr x))
(define first ()
(begin
(set currentKey 1)
(set currentCell self)
car))
(define next ()
(if (isNil (car currentCell)) #nil
(begin
(set currentKey (+1 currentKey))
(set currentCell (cdr currentCell))
(car currentCell))))
(define firstKey () 1)
(define lastKey () (size self))
(define currentKey () currentKey)
(define at:put: (n value)
(if (= n 1) (set car value)
(at:put: cdr (- n 1) value)))
(define removeFirst ()
(if (isEmpty self) self ; do nothing
(begin
(set car (car cdr))
(set cdr (cdr cdr)))))
(define zerolist (size)
(while (> size 0)
(begin
(add: self 0)
(set size (- size 1)))))
)
(define mkList () (initList (new List)))
;
(class Array SequenceableCollection
(elements lobound hibound currentKey)
(define initArray (lo size)
(begin
(set lobound lo)
(set hibound (- (+ lo size) 1))
(set elements (new List))
(zerolist elements size)
self))
(define size () (+1 (- hibound lobound)))
(define firstKey () lobound)
(define lastKey () hibound)
(define currentKey () currentKey)
(define first ()
(begin
(set currentKey lobound)
(first elements)))
(define next ()
(if (= currentKey hibound) #nil
(begin
(set currentKey (+1 currentKey))
(next elements))))
(define at:put: (n value)
(if (> n hibound) #nil
(if (< n lobound) #nil
(at:put: elements (+1 (- n lobound)) value))))
)
(define mkArray (l s) (initArray (new Array) l s))
; Test cases for FinancialHistory and DeductibleHistory
(set myaccount (mkFinancialHistory 1000))
(spend:for: myaccount 50 #insurance)
(receive:from: myaccount 200 #salary)
(cashOnHand myaccount)
1150
(spend:for: myaccount 100 #books)
(cashOnHand myaccount)
1050
(set myaccount (mkDeductibleHistory 1000))
(spend:for: myaccount 50 #insurance)
(receive:from: myaccount 200 #salary)
(cashOnHand myaccount)
1150
(totalDeductions myaccount)
0
(spend:Deduct: myaccount 100 #mortgage)
(cashOnHand myaccount)
1050
(totalDeductions myaccount)
100
(spend:for:deduct: myaccount 100 #3-martini-lunch 50)
(cashOnHand myaccount)
950
(totalDeductions myaccount)
150
; Section 7.3
(class Number Object
() ; abstract class
(define + (x) #subclassResponsibility)
(define negate () #subclassResponsibility)
(define * (x) #subclassResponsibility)
(define recip () #subclassResponsibility)
(define = (x) #subclassResponsibility)
(define < (x) #subclassResponsibility)
(define zero () #subclassResponsibility)
(define one () #subclassResponsibility)
(define print () #subclassResponsibility)
(define - (y) (+ self (negate y)))
(define / (y) (* self (recip y)))
(define > (y) (< y self))
(define +1 () (+ self (one self)))
(define sub1 () (- self (one self)))
(define isZero () (= self (zero self)))
(define isNegative () (< self (zero self)))
(define abs () (if (isNegative self) (negate self) self))
(define sqr () (* self self))
(define sqrt (epsilon) ; find square root of receiver within epsilon
(begin
(set this-step (+1 (zero self)))
(set two (+1 this-step))
(set next-step (/ (+ this-step (/ self this-step)) two))
(while (> (abs (- this-step next-step)) epsilon)
(begin
(set this-step next-step)
(set next-step (/
(+ this-step (/ self this-step)) two))))
next-step))
)
(class Fraction Number
(x y)
(define initFraction (a b)
(begin
(setFraction self a b)
(sign-reduce self)
(div-reduce self)))
(define setFraction (a b) (begin (set x a) (set y b) self))
(define x () x)
(define y () y)
(define + (f)
(div-reduce
(setFraction (new Fraction)
(+ (* x (y f)) (* (x f) y))
(* y (y f)))))
(define negate () (setFraction (new Fraction) (- 0 x) y))
(define * (f)
(div-reduce
(setFraction (new Fraction)
(* x (x f))
(* y (y f)))))
(define recip ()
(sign-reduce (setFraction (new Fraction) y x)))
(define = (f)
(and (= x (x f)) (= y (y f))))
(define < (f)
(< (* x (y f)) (* (x f) y)))
(define zero () (setFraction (new Fraction) 0 1))
(define one () (setFraction (new Fraction) 1 1))
(define print () (begin (print x) (print y)))
; div-reduce and sign-reduce should not be exported
(define div-reduce ()
(begin
(if (= x 0)
(set y 1)
(begin
(set temp (gcd (abs x) y))
(set x (/ x temp))
(set y (/ y temp))))
self))
(define sign-reduce ()
(begin
(if (< y 0)
(begin (set x (- 0 x))(set y (- 0 y)))
0)
self))
)
(define mkFraction (a b) (initFraction (new Fraction) a b))
(set eps (mkFraction 1 2))
(set f1 (mkFraction 17 1))
(set f2 (sqrt f1 eps))
(print f2)
3437249
833049
;
(class Float Number
(mant exp)
(define initFloat (m e)
(begin (set mant m) (set exp e) self))
(define mant () mant)
(define exp () exp)
(define + (x)
(begin
(if (< exp (exp x))
(begin
(set min self)
(set max x))
(begin
(set min x)
(set max self)))
(set delta (- (exp max) (exp min)))
(set temp (+ (* (mant max) (powerof10 self delta)) (mant min)))
(normalize
(initFloat (new Float) temp (if (= temp 0) 0 (exp min))))))
(define negate () (initFloat (new Float) (- 0 mant) exp))
(define * (x)
(normalize (initFloat (new Float)
(* mant (mant x))
(+ exp (exp x)))))
(define recip ()
(if (isZero self) self
(normalize (initFloat (new Float)
(/ 100000000 mant)
(- (- 0 8) exp)))))
(define zero () (initFloat (new Float) 0 0))
(define one () (initFloat (new Float) 1 0))
(define = (x) (isZero (- self x)))
(define < (x) (isNegative (- self x)))
(define print () (begin (print mant) (print exp)))
(define isZero () (= mant 0))
(define isNegative () (< mant 0))
; normalize and powerof10 should not be exported
(define powerof10 (d)
(if (= d 0) 1 (* 10 (powerof10 self (- d 1)))))
(define normalize ()
(begin
(while (> (abs mant) 10000)
(begin
(set mant (/ mant 10))
(set exp (+ exp 1))))
self))
)
(define mkFloat (m e) (initFloat (new Float) m e))
(set eps (mkFloat 5 -1))
(set x1 (mkFloat 17 0))
(print (sqrt x1 eps))
4125
-3
; Section 7.4
(class Simulation Object
() ; abstract class
(define initialize () #subclassResponsibility)
(define report () #subclassResponsibility)
(define run (timelimit)
(begin
(set CLOCK 0)
(set EVQUEUE (mkEventQueue))
(initialize self)
(while (<= CLOCK timelimit) (doNextEvent EVQUEUE))
(report self)))
)
(class LabSimulation Simulation
(termlimit)
(define initLabSimulation (t)
(begin (set termlimit t) self))
(define initialize ()
(begin
(set TERMINALLIMIT termlimit)
(set THELAB (mkLab))
(set STUDENTNO 0)
(set STUDENTSFINISHING 0)
(set TOTALTIMEWASTED 0)
(set TERMINALQUEUE (mkQueue))
(set WAITTIMES (mkWaitTimeList))
(set SERVICETIMES (mkServiceTimeList))
(scheduleNewArrival (new Student))))
(define report ()
(begin
(print #simulation-done)
(print #students-finishing)
(print STUDENTSFINISHING)
(print #left-on-queue)
(print (size TERMINALQUEUE))
(print #Total-time-wasted:)
(print TOTALTIMEWASTED)
(print #Average-time-wasted:)
(print (/ TOTALTIMEWASTED STUDENTSFINISHING))))
)
(define mkLabSimulation (tl) (initLabSimulation (new LabSimulation) tl))
(class Lab Object
(term1free term2free)
(define initLab ()
(begin (set term1free true) (set term2free true) self))
(define terminals-free? () (or term1free term2free))
(define pick-terminal ()
(if term1free
(begin (set term1free false) 1)
(begin (set term2free false) 2)))
(define release-terminal (t)
(if (= t 1) (set term1free true) (set term2free true)))
)
(define mkLab () (initLab (new Lab)))
;
(class List SequenceableCollection
(car cdr currentKey currentCell)
(define car () car)
(define cdr () cdr)
(define initList ()
(begin (set car #nil) self))
(define newEmptyCollection () (initList (new List)))
(define add: (item)
(begin
(set temp (newEmptyCollection self))
(car: temp car)
(cdr: temp cdr)
(set cdr temp)
(set car item)))
(define car: (x) (set car x))
(define cdr: (x) (set cdr x))
(define first ()
(begin
(set currentKey 1)
(set currentCell self)
car))
(define next ()
(if (isNil (car currentCell)) #nil
(begin
(set currentKey (+1 currentKey))
(set currentCell (cdr currentCell))
(car currentCell))))
(define firstKey () 1)
(define lastKey () (size self))
(define currentKey () currentKey)
(define at:put: (n value)
(if (= n 1) (set car value)
(at:put: cdr (- n 1) value)))
(define removeFirst ()
(if (isEmpty self) self ; do nothing
(begin
(set car (car cdr))
(set cdr (cdr cdr)))))
(define zerolist (size)
(while (> size 0)
(begin
(add: self 0)
(set size (- size 1)))))
)
;
(class Queue List
()
(define initQueue () (initList self))
(define newEmptyCollection () (initList (new Queue)))
(define enqueue: (item)
(if (isEmpty self) (add: self item) (enqueue: cdr item)))
)
(define mkQueue () (initQueue (new Queue)))
(class EventQueue Object
(pqueue) ; a PriorityQueue
(define initEventQueue ()
(begin (set pqueue (mkPriorityQueue)) self))
(define scheduleEvent (event time)
(insert: pqueue (mkAssociation time event)))
(define doNextEvent ()
(begin
(set pair (car pqueue))
(removeFirst pqueue)
(set CLOCK (fst pair))
(takeAction (snd pair))))
)
(define mkEventQueue () (initEventQueue (new EventQueue)))
(class PriorityQueue List
()
(define initPriorityQueue () (initList self))
(define newEmptyCollection () (initList (new PriorityQueue)))
(define insert: (pair)
(if (isEmpty self) (add: self pair)
(if (< (fst pair) (fst car)) (add: self pair)
(insert: cdr pair))))
)
(define mkPriorityQueue () (initPriorityQueue (new PriorityQueue)))
(class Student Object
(status number timeNeeded timeStillNeeded arrivalTime)
(define initStudent (n t a)
(begin
(set status -1)
(set number n)
(set timeNeeded t)
(set timeStillNeeded t)
(set arrivalTime a)
self))
(define takeAction ()
(if (= status -1) (arrive self) (leaveTerminal self)))
(define arrive ()
(begin
(if (terminals-free? THELAB)
(grabTerminal self)
(begin
(set status 0)
(enqueue: TERMINALQUEUE self)))
(scheduleNewArrival (new Student))))
(define leaveTerminal ()
(if (= timeStillNeeded 0)
(begin
(release-terminal THELAB status)
(set status 3)
(set wasted (- (- CLOCK arrivalTime) timeNeeded))
(set STUDENTSFINISHING (+1 STUDENTSFINISHING))
(set TOTALTIMEWASTED (+ TOTALTIMEWASTED wasted))
(if (not (isEmpty TERMINALQUEUE))
(grabTerminal (car TERMINALQUEUE)) 0))
(if (isEmpty TERMINALQUEUE)
(scheduleLeaveTerminal self)
(begin
(release-terminal THELAB self)
(set status 0)
(enqueue: TERMINALQUEUE self)
(grabTerminal (car TERMINALQUEUE))))))
(define grabTerminal ()
(begin
(if (= status 0) ; was on terminal queue
(removeFirst TERMINALQUEUE)
0) ; else do nothing
(set status (pick-terminal THELAB))
(scheduleLeaveTerminal self)))
(define scheduleLeaveTerminal ()
(if (<= timeStillNeeded TERMINALLIMIT)
(begin
(scheduleEvent EVQUEUE self (+ CLOCK timeStillNeeded))
(set timeStillNeeded 0))
(begin
(scheduleEvent EVQUEUE self (+ CLOCK TERMINALLIMIT))
(set timeStillNeeded (- timeStillNeeded TERMINALLIMIT)))))
(define scheduleNewArrival ()
(begin
(set wait (next WAITTIMES))
(set service (next SERVICETIMES))
(set STUDENTNO (+1 STUDENTNO))
(set arrival (+ CLOCK wait))
(initStudent self STUDENTNO service arrival)
(scheduleEvent EVQUEUE self arrival)))
)
; Twenty arrivals at time zero
(class WaitTimeList Object
(which)
(define initWaitTimeList () (begin (set which 0) self))
(define next ()
(if (= which 20) 2000 (begin (set which (+1 which)) 0)))
)
(define mkWaitTimeList () (initWaitTimeList (new WaitTimeList)))
; All students need 120 minutes of terminal time
(class ServiceTimeList Object
()
(define initServiceTimeList () self)
(define next () 120)
)
(define mkServiceTimeList () (initServiceTimeList (new ServiceTimeList)))
(set sim30 (mkLabSimulation 30))
(run sim30 1200)
#simulation-done
#students-finishing
20
#left-on-queue
0
#Total-time-wasted:
18900
#Average-time-wasted:
945
; Arrivals every 30 minutes
(class WaitTimeList Object
()
(define initWaitTimeList () self)
(define next () 30)
)
(define mkWaitTimeList () (initWaitTimeList (new WaitTimeList)))
; Service times alternating: 120, 30, 120, 30, ...
(class ServiceTimeList Object
(which)
(define initServiceTimeList () (begin (set which 1) self))
(define next ()
(begin
(set which (- 1 which))
(if (= which 0) 120 30)))
)
(define mkServiceTimeList () (initServiceTimeList (new ServiceTimeList)))
(set sim30 (mkLabSimulation 30))
(run sim30 1200)
#simulation-done
#students-finishing
30
#left-on-queue
8
#Total-time-wasted:
3090
#Average-time-wasted:
103
quit