 (defn search [db & people]
   (mapv (partial name-or-search db) people))
 
+(let [add (fnil conj #{})]
+  (defn- add-reducer
+    ([] {})
+    ([map [key val]]
+     (update-in map [key] add val))))
+
 (defn- map-set-pairs [map pairs]
-  (let [add (fnil conj #{})]
-    (reduce (fn [map [key val]]
-              (update-in map [key] add val))
-            map
-            pairs)))
+  (reduce add-reducer map pairs))
 
 (defn paths
   "Returns a lazy seq of all non-looping path vectors starting with

                          :when (not (contains? succs nbr))]
                      [nbr node])
              succs (map-set-pairs succs pairs)
              q2 (set (map first pairs))]
          (if-let [all (seq (filter #(contains? preds %) q2))]
            (find-paths preds succs all)
            (recur preds succs q1 q2 (inc iter))))))))

(defn bidirectional-bfs [start end neighbors]
  (loop [preds {start nil}
         succs {end nil}
         q1 (list start)
         q2 (list end)
         iter 1]
    (when (and (seq q1) (seq q2) (< iter 11)) ; 5 "hops" or fewer
      (if (<= (count q1) (count q2))
        (let [pairs (for [node q1
                          nbr (neighbors node)
                          :when (not (contains? preds nbr))]
                      [nbr node])
              preds (map-set-pairs preds pairs)
              q1 (map first pairs)]
          (if-let [all (seq (filter #(contains? succs %) q1))]
            (find-paths preds succs all)
            (recur preds succs q1 q2 (inc iter))))
