                         (map f coll)))
          m ks nil))
 
+(t/ann reduce-in (t/All [x]
+                   (t/IFn [x (t/Vec t/Any) (t/IFn [t/Any -> t/Any]) -> x]
+                         [x (t/Vec t/Any) (t/IFn [t/Any -> t/Any]) t/Any -> x])))
 (defn reduce-in
   "Reduce a value inside an associative datastructure. `more` can be either
   a reducing function, a reducting function and an initial value."

(t/ann ^:no-check taoensso.timbre/refer-timbre [-> t/Any])
(timbre/refer-timbre)

(t/ann uniform-int (t/Fn [Integer -> Integer]
                         [Integer Integer -> Integer]))
(defn uniform-int
 ([hi] (uniform-int 0 hi))
 ([lo hi] {:pre [(< lo hi)]} (int (dg/uniform lo hi))))

(defmacro log-time
  "Log the time it takes to execute body."

  `(condp vec-match? ~match
     ~@body))

(t/ann noun->indefinite-article (t/Pred String))
(defn noun->indefinite-article [noun] (if (contains? #{\a \e \i \o \u} (first noun))
                                        "an"
                                        "a"))
(t/defalias Pos (t/HMap :mandatory {:x Integer :y Integer}))

(t/ann pos->xy (t/IFn [Pos -> (t/Vec Number)]))
(defn pos->xy
  [{x :x y :y}]
  [x y])

(t/ann xy->pos (t/IFn [Number Number -> Pos]))
(defn xy->pos
  [x y]
  {:x x :y y})

(t/ann chebyshev-distance (t/IFn [Pos Pos -> Number]))
(defn chebyshev-distance
  "Chebyshev/chessboard distance between 2 points"
  [p1 p2]
  (max (Math/abs (- (:x p1) (:x p2)))
       (Math/abs (- (:y p1) (:y p2)))))

(t/ann distance-sq (t/IFn [Pos Pos -> Number]))
(defn distance-sq
  [p1 p2]
  (let [sq (fn [x] (* x x))]
  (+ (sq (- (:x p1) (:x p2)))
     (sq (- (:y p1) (:y p2))))))

(t/ann distance (t/IFn [Pos Pos -> Number]))
(defn distance
  "Euclidean distance between 2 points"
  [p1 p2]
  (Math/sqrt (distance-sq p1 p2)))

(t/ann farther-than? [Pos Pos Number -> Boolean])
(defn farther-than?
  "Are the two points farther in distance than l?"
  [p1 p2 l]
  (> (distance-sq p1 p2) (* l l)))

(t/ann fill-missing (t/All [x y z] (t/IFn [(t/Pred x)
                                           (t/IFn [x y -> z])
                                           (t/Seq y)
                                           (t/Seq x) -> (t/Seq z)])))
                                   
(defn fill-missing
  "For each item in coll for which (pred item) returns true, replace that
   element with the result of (f item vcoll-item) where vcoll-item
