Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; The Santa Claus Problem
- ; Santa repeatedly sleeps until wakened by either all of his
- ; nine reindeer, back from their holidays, or by a group of three
- ; of his ten elves. If awakened by the reindeer, he harnesses
- ; each of them to his sleight, delivers toys with them, and finally
- ; unharnesses them (allowing them to go off on holiday). If
- ; awakened by a group of elves, he shows each of the group into
- ; his study, consults with them on toy R&D, and finally shows them
- ; each out (allowing them to go back to work). Santa should give
- ; priority to the reindeer in the case that there is both a group
- ; of elves and a group of reindeer waiting.
- ; Text copied verbatim from http://www.cs.otago.ac.nz/staffpriv/ok/santa/santa.erl
- ; and code inspired by that solution.
- ; See also http://www.cs.otago.ac.nz/staffpriv/ok/santa/
- ; maximum time a worker waits before having a problem/returning from leave
- (def work-time 1000)
- ; time for secretary to wait before trying again when meeting room is full
- (def wait-time 10)
- ; Santa's meeting room
- (def meeting-room (ref #{}))
- (declare do-work)
- (defn worker-done
- "Santa removes worker from meeting room and sends him back to work."
- [santa-state worker]
- (dosync
- ; remove worker from meeting room ...
- (ref-set meeting-room (filter #(not (= % worker)) @meeting-room)))
- ; ... and send him back to work
- (send-off worker do-work)
- santa-state)
- (defn state-business
- "Worker gives Santa his message, then tells Santa he's done."
- [worker-state santa]
- (println (:msg worker-state))
- (send-off santa worker-done *agent*)
- worker-state)
- (defn call-meeting
- "Santa decides what to do by species, then tells each worker in the meeting room to state their business."
- [santa-state species]
- (println (str
- "Ho, ho, ho! Let's "
- (if (= species :reindeer)
- "deliver toys!"
- "meet in the study!")))
- (doseq [worker @meeting-room]
- (send-off worker state-business *agent*))
- santa-state)
- (defn need-santa
- "If secretary has count workers, sends them to Santa's meeting room and notifies Santa otherwise waits for more."
- [sec-state worker]
- (let [workers-waiting (conj (:waiting sec-state) worker)]
- (assoc sec-state :waiting
- (if (= (:count sec-state) (count workers-waiting))
- (do
- (loop []
- (if (not
- (dosync
- (if (empty? @meeting-room) ; only transfer workers to santa if meeting room is empty
- (do
- (doseq [w workers-waiting] (ref-set meeting-room (conj @meeting-room w)))
- (send-off (:santa sec-state) call-meeting (:species sec-state))
- true)
- false))) ; dosync returns false if unable to transfer to santa i.e. meeting room wasn't empty
- (do
- (println "*** blocked ***")
- (Thread/sleep wait-time) ; if it's not empty wait wait-time and try again
- (recur))))
- #{}) ; if successful Santa transfer, reset 'waiting' to empty set
- workers-waiting)))) ; otherwise append latest worker to 'waiting'
- (defn do-work
- "Worker works/holidays for a random time, then needs to see Santa. Tells his secretary."
- [worker-state]
- (Thread/sleep (rand work-time))
- (send-off (:secretary worker-state) need-santa *agent*)
- worker-state)
- (defn create-worker
- "Creates a worker with specfied secretary and message to deliver to Santa when he asks."
- [secretary msg]
- (agent {:secretary secretary :msg msg}))
- (defn create-secretary
- "Creates a secretary for specified species. Will hold up to count workers before sending to Santa."
- [santa species count]
- (agent {:santa santa :species species :count count :waiting #{}}))
- (defn start
- "Creates Santa, secretary for each species, elves and reindeer and sends them to work"
- []
- (let [santa (agent nil)
- robin (create-secretary santa :reindeer 9)
- edna (create-secretary santa :elves 3)]
- ; create reindeer
- (dorun (map #(send-off (create-worker robin (str "Reindeer " % " delivering toys.")) do-work) (range 1 10)))
- ; create elves
- (dorun (map #(send-off (create-worker edna (str "Elf " % " meeting in the study.")) do-work) (range 1 11)))))
- (start)
Advertisement
Add Comment
Please, Sign In to add comment