Skip to content

Instantly share code, notes, and snippets.

@RyanGough
Created October 13, 2015 21:51
Show Gist options
  • Save RyanGough/99bda5c5c60f3c328dd8 to your computer and use it in GitHub Desktop.
Save RyanGough/99bda5c5c60f3c328dd8 to your computer and use it in GitHub Desktop.
Initial stab at a very basic implmentation of the lift / elevator kata in clojure.
(ns lift-kata.core-test
(:require [clojure.test :refer :all]
[lift-kata.core :refer :all]))
(deftest open-door-on-requested-floor
(testing "Should open the doors if only request is current floor."
(is (= {:doors :open :floor 0 :requests []}
(lift-kata.core/next-lift-state {:doors :closed :floor 0 :requests[]},
[0])))))
(deftest move-up-one-floor-towards-request
(testing "Should move up one floor if the request is two floors above."
(is (= {:doors :closed :floor 1 :requests [2]}
(lift-kata.core/next-lift-state {:doors :closed :floor 0 :requests []},
[2])))))
(deftest moving-down-two-floors-then-opening-doors
(testing "Given a request two floors below, will in two moves be on the correct
floor with the doors open."
(is (= {:doors :open :floor 0 :requests []}
( -> {:doors :closed :floor 2 :requests []}
(lift-kata.core/next-lift-state [0])
(lift-kata.core/next-lift-state []))))))
(deftest adding-multiple-requests
(testing "with lift on floor 0, after request for floors 2 & 3,
then request for floor 4, after two moves the lift is on the
second floor with open doors and requests for floor 3 and 4
remain."
(is (= {:doors :open :floor 2 :requests [3,4]}
( -> {:doors :closed :floor 0 :requests []}
(lift-kata.core/next-lift-state [2,3])
(lift-kata.core/next-lift-state [4]))))))
(ns lift-kata.core)
(defn merge-requests
"Merge new floor requests into the requests vector"
[liftState, floorRequests]
(assoc liftState :requests
(into
(vector)
(concat (liftState :requests) floorRequests))))
(defn move-lift
"Move the lift based on the current floor and the requests"
[liftState]
(cond
(empty? (liftState :requests))
liftState
(< (liftState :floor) (first (liftState :requests)))
(update-in liftState [:floor] inc)
(> (liftState :floor) (first (liftState :requests)))
(update-in liftState [:floor] dec)
(= (liftState :floor) (first (liftState :requests)))
liftState))
(defn remove-floor-from-requests
"Remove the current floor from the vector of requests"
[liftState]
(assoc liftState :requests
(into
(vector)
(remove (fn [x] (= x (liftState :floor))) (liftState :requests)))))
(defmulti open-lift-doors (fn [liftState] (= (liftState :floor) (first (liftState :requests)))))
(defmethod open-lift-doors true
[liftState]
( -> liftState
(update-in [:doors] (fn [x] :open))
remove-floor-from-requests))
(defmethod open-lift-doors false
[liftState]
(update-in liftState [:doors] (fn [x] :closed)))
(defn next-lift-state
"Takes the current lift state & and a list of floor requests and returns the updated
lift state."
[liftState, floorRequests]
(-> liftState
(merge-requests floorRequests)
move-lift
open-lift-doors))
@RyanGough
Copy link
Author

Started doing the lift / elevator kata in clojure. This is a very basic implementation, am hoping to refine towards a smarter algorithm at some point :)

@RyanGough
Copy link
Author

Probably unnecessary use of multimethods but I wanted to try them out. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment