September 14, 2018

Just Juxt #31: Graph Tour (4clojure #89)

Eulerian Path

Starting with a graph you must write a function that returns true if it is possible to make a tour of the graph in which every edge is visited exactly once.

The graph is represented by a vector of tuples, where each tuple represents a single edge.

The rules are:

  • You can start at any node.
  • You must visit each edge exactly once.
  • All edges are undirected.
(ns live.test
  (:require [cljs.test :refer-macros [deftest is testing run-tests]]))
  
(defn eulerian [g]
  (if (= (count g) (count (distinct g)))
      (let [g (apply merge-with clojure.set/union
                (mapcat (fn [[k v]] [{k #{v}} {v #{k}}]) g))
            f (fn [[s k]]
                (->> (g k)
                  (remove s)
                  (map #(vector (conj s %) %))))
            p (map (juxt hash-set identity) (keys g))]
        (not (empty? (nth (iterate (partial mapcat f) p) (dec (count g))))))
      false))

(deftest eulerian-test
  (is (= true (eulerian [[:a :b]])))
  (is (= false (eulerian [[:a :a] [:b :b]])))
  (is (= false (eulerian [[:a :b] [:a :b] [:a :c] [:c :a]
                          [:a :d] [:b :d] [:c :d]])))
  (is (= true (eulerian [[1 2] [2 3] [3 4] [4 1]])))
  (is (= true (eulerian [[:a :b] [:a :c] [:c :b] [:a :e]
                         [:b :e] [:a :d] [:b :d] [:c :e]
                         [:d :e] [:c :f] [:d :f]])))
  (is (= false (eulerian [[1 2] [2 3] [2 4] [2 5]]))))
  
(run-tests)
Tags: coding exercises KLIPSE 4clojure Cryogen juxt