Skip to content

Instantly share code, notes, and snippets.

@teropa
Created May 25, 2012 12:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teropa/2787639 to your computer and use it in GitHub Desktop.
Save teropa/2787639 to your computer and use it in GitHub Desktop.
Reservation puzzle, one possible solution
(def seats (-> (repeat 5000 nil) vec ref))
(def clerks (repeatedly 10 #(agent 0)))
(defn available-indexes
"Given a sequence of seats, returns a (lazy)
sequence of the indexes of the available seats.
This is purely functional and doesn't know anything
about refs or agents"
[seats]
(keep-indexed
(fn [idx s] (when-not s idx))
seats))
(defn reserve-seats
"Given a vector of seats and a sequence of seat indexes
to reserve, return a new vector of seats where the given
indexes are marked reserved (as :x).
This is also purely functional. Notice the use of assoc
to 'change' the value in a specific index of a vector."
[seats indexes]
(reduce #(assoc %1 %2 :x) seats indexes))
(defn reserve
"The agent action. Gets all available seats, and takes
at most n-seats of them. Marks the taken seats as reserved,
and returns the new bonus for this clerk."
[previous-bonus n-seats]
(dosync
(let [avail (take n-seats (available-indexes @seats))]
(alter seats reserve-seats avail)
(+ previous-bonus (count avail)))))
; Test code
(map
(fn [n-seats clerk]
(send clerk reserve n-seats))
(repeatedly 1000 #(rand-int 10))
(cycle clerks))
@seats ; -> Reservation situation
(map deref clerks) ; -> Number of reservations by each clerk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment