Guest User

gps408

a guest
May 5th, 2009
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 4.12 KB | None | 0 0
  1. ; The Santa Claus Problem
  2.  
  3. ; Santa repeatedly sleeps until wakened by either all of his
  4. ; nine reindeer, back from their holidays, or by a group of three
  5. ; of his ten elves.  If awakened by the reindeer, he harnesses
  6. ; each of them to his sleight, delivers toys with them, and finally
  7. ; unharnesses them (allowing them to go off on holiday).  If
  8. ; awakened by a group of elves, he shows each of the group into
  9. ; his study, consults with them on toy R&D, and finally shows them
  10. ; each out (allowing them to go back to work).  Santa should give
  11. ; priority to the reindeer in the case that there is both a group
  12. ; of elves and a group of reindeer waiting.
  13.  
  14. ; Text copied verbatim from http://www.cs.otago.ac.nz/staffpriv/ok/santa/santa.erl
  15. ; and code inspired by that solution.
  16. ; See also http://www.cs.otago.ac.nz/staffpriv/ok/santa/
  17.  
  18. ; maximum time a worker waits before having a problem/returning from leave
  19. (def work-time 1000)
  20.  
  21. ; time for secretary to wait before trying again when meeting room is full
  22. (def wait-time 10)
  23.  
  24. ; Santa's meeting room
  25. (def meeting-room (ref #{}))
  26.  
  27. (declare do-work)
  28.  
  29. (defn worker-done
  30.   "Santa removes worker from meeting room and sends him back to work."
  31.   [santa-state worker]
  32.   (dosync
  33.    ; remove worker from meeting room ...
  34.    (ref-set meeting-room (filter #(not (= % worker)) @meeting-room)))
  35.   ; ... and send him back to work
  36.   (send-off worker do-work)
  37.   santa-state)
  38.  
  39. (defn state-business
  40.   "Worker gives Santa his message, then tells Santa he's done."
  41.   [worker-state santa]
  42.   (println (:msg worker-state))
  43.   (send-off santa worker-done *agent*)
  44.   worker-state)
  45.  
  46. (defn call-meeting
  47.   "Santa decides what to do by species, then tells each worker in the meeting room to state their business."
  48.   [santa-state species]
  49.   (println (str
  50.         "Ho, ho, ho! Let's "
  51.         (if (= species :reindeer)
  52.           "deliver toys!"
  53.           "meet in the study!")))
  54.   (doseq [worker @meeting-room]
  55.     (send-off worker state-business *agent*))
  56.   santa-state)
  57.  
  58. (defn need-santa
  59.   "If secretary has count workers, sends them to Santa's meeting room and notifies Santa otherwise waits for more."
  60.   [sec-state worker]
  61.   (let [workers-waiting (conj (:waiting sec-state) worker)]
  62.     (assoc sec-state :waiting
  63.        (if (= (:count sec-state) (count workers-waiting))
  64.          (do
  65.            (loop []
  66.          (if (not
  67.               (dosync
  68.                (if (empty? @meeting-room) ; only transfer workers to santa if meeting room is empty
  69.              (do
  70.                (doseq [w workers-waiting] (ref-set meeting-room (conj @meeting-room w)))
  71.                (send-off (:santa sec-state) call-meeting (:species sec-state))
  72.                true)
  73.              false))) ; dosync returns false if unable to transfer to santa i.e. meeting room wasn't empty
  74.            (do
  75.              (println "*** blocked ***")
  76.              (Thread/sleep wait-time) ; if it's not empty wait wait-time and try again
  77.              (recur))))
  78.            #{}) ; if successful Santa transfer, reset 'waiting' to empty set
  79.          workers-waiting)))) ; otherwise append latest worker to 'waiting'
  80.  
  81. (defn do-work
  82.   "Worker works/holidays for a random time, then needs to see Santa.  Tells his secretary."
  83.   [worker-state]
  84.   (Thread/sleep (rand work-time))
  85.   (send-off (:secretary worker-state) need-santa *agent*)
  86.   worker-state)
  87.  
  88. (defn create-worker
  89.   "Creates a worker with specfied secretary and message to deliver to Santa when he asks."
  90.   [secretary msg]
  91.   (agent {:secretary secretary :msg msg}))
  92.  
  93. (defn create-secretary
  94.   "Creates a secretary for specified species.  Will hold up to count workers before sending to Santa."
  95.   [santa species count]
  96.   (agent {:santa santa :species species :count count :waiting #{}}))
  97.  
  98. (defn start
  99.   "Creates Santa, secretary for each species, elves and reindeer and sends them to work"
  100.   []
  101.   (let [santa (agent nil)
  102.     robin (create-secretary santa :reindeer 9)
  103.     edna (create-secretary santa :elves 3)]
  104.     ; create reindeer
  105.     (dorun (map #(send-off (create-worker robin (str "Reindeer " % " delivering toys.")) do-work) (range 1 10)))
  106.     ; create elves
  107.     (dorun (map #(send-off (create-worker edna (str "Elf " % " meeting in the study.")) do-work) (range 1 11)))))
  108.  
  109. (start)
Advertisement
Add Comment
Please, Sign In to add comment