(defn select [v i] ; INPUT: a vector v and an index i ; OUTPUT: a vector containing only the i-th element of v (into (subvec v 0 i) (subvec v (+ i 1) (count v))) ) (defn allperm [ v ] ; INPUT: a vector v ; OUTPUT: a list of all permutations of elements in v ; if v is empty, then the only possible permutation is the empty vector (if (= v []) '([]) ; (D) store everything in a list (reduce into ; (C) do it for each element in i (for [i (range (count v))] ; (B) add back element i as head of each permutation (map (partial into (subvec v i (inc i))) ; (A) remove element i and generate all permutations of remaining elements (allperm (select v i) ) ; end allperm ); end map ); end for ); end reduce ); end if ); end defn (defn mand [ a b ] (and a b)) (defn mor [ a b ] (or a b)) (defn checkxml [ s t ] ; INPUT: two (parsed) xml trees ; OUTPUT: true if s and t equivalent ; OUTPUT: false otherwise (cond ;both empty? (and (empty? s) (empty? t)) true ;is one of them empty (and the other not)? (or (empty? s) (empty? t)) false ;check tags (not (= (get s :tag) (get t :tag))) false ;check singletons (only a data format shortcut) (and (= (count (get s :content) ) 1) (= (count (get t :content) ) 1) ) true ;check number of children (only a speedup) (not (= (count (get s :content)) (count (get t :content)) ) ) false ;otherwise :else (reduce mor ; try to permute the children of t (for [p (allperm (get t :content))] ; is there a full matching with the children of s? (reduce mand (map checkxml (get s :content) p) ) ); end for ); end reduce or ) ) (use 'clojure.xml) (def x (parse "tracks.xml")) (def y (parse "otracks.xml")) (checkxml x y)