Skip to content

Instantly share code, notes, and snippets.

@srazzaque
Last active September 9, 2015 09:09
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 srazzaque/7be0482c606506a8b860 to your computer and use it in GitHub Desktop.
Save srazzaque/7be0482c606506a8b860 to your computer and use it in GitHub Desktop.
(ns trains
(:import java.time.LocalDateTime
java.time.format.DateTimeFormatter))
(def trips
;; Each trip is a uni-directional trip.
[{:id 0,
:stops [{:stop "Wynyard"
:time "2015-07-15T18:47"}
{:stop "Town Hall"
:time "2015-07-15T18:49"}
{:stop "Central"
:time "2015-07-15T18:53"}
{:stop "Redfern"
:time "2015-07-15T18:55"}]}
{:id 1,
:stops [{:stop "Wynyard"
:time "2015-07-15T18:48"}
{:stop "Town Hall"
:time "2015-07-15T18:50"}
{:stop "Redfern"
:time "2015-07-15T18:54"}
{:stop "Redfern"
:time "2015-07-15T18:56"}]}])
(defn- parse-date
[date-str]
(LocalDateTime/parse date-str DateTimeFormatter/ISO_DATE_TIME))
(defn- is-date-after?
[date1 date2]
(.isAfter (parse-date date1)
(parse-date date2)))
(defn goes-to?
"Returns 'true' if the given trip stops at the origin THEN the destination."
[origin destination trip]
(let [ts (filter #(or (= origin %)
(= destination %))
(map :stop (:stops trip)))]
(if (seq ts)
(and (= origin (first ts))
(= destination (first (rest ts)))))))
(defn- get-stop-info
"Gets the stop info for a stop in the context of a given trip"
[trip stop]
(if-let [ts (seq (filter #(= stop (:stop %)) (:stops trip)))]
(first ts)))
(defn is-after?
"Returns 'true' if the given trip gets to the origin after the given time."
[origin time trip]
(if-let [stop-info (get-stop-info trip origin)]
(is-date-after? (:time stop-info)
time)))
(defn get-all-trips
"Returns all trips after 'time-now' that can take someone from 'origin' to 'destination'"
[trips time-now origin destination]
(->> trips
(filter (partial goes-to? origin destination))
(filter (partial is-after? origin time-now))))
(defn- get-time-at
"Given a stop and a trip, gets the time of the trip at that stop"
[stop trip]
(if-let [stop-info (get-stop-info trip stop)]
(:time stop-info)))
(defn earliest
"Given a stop and 2 trips, returns the trip which arrives
at that stop earlier"
[stop trip1 & [trip2 _]]
(if (and trip2
(is-date-after? (get-time-at stop trip1)
(get-time-at stop trip2)))
trip2
trip1))
(defn get-earliest
[trips time-now origin destination]
(let [reduce-fn (partial earliest origin)
candidates (get-all-trips trips time-now origin destination)]
(if (seq candidates)
(reduce reduce-fn
candidates))))
(defn run-tests
"Some really basic tests (obviously we'd use clojure.test for this in a real app)"
[]
(assert (= 0 (:id (get-earliest trips "2015-07-15T18:46" "Wynyard" "Town Hall"))))
(assert (= 1 (:id (get-earliest trips "2015-07-15T18:47" "Wynyard" "Town Hall"))))
(assert (nil? (get-earliest trips "2015-07-15T18:48" "Wynyard" "Town Hall")))
(assert (nil? (get-earliest trips "2015-07-15T18:46" "Town Hall" "Wynyard"))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment