forked from stevewitman/challenges
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproblem_2.cljc
More file actions
74 lines (63 loc) · 2.73 KB
/
problem_2.cljc
File metadata and controls
74 lines (63 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
(ns cljs-solutions.problem_2
[:require [clojure.set :refer [intersection]]
[clojure.string :refer [upper-case]]])
(defn- subseqs-by-count
"Returns a lazy seq of sets of subsequences of the members of the given
sequable. Each of the returned subsequences within its set will have the
same count as the others there, and these containing sets in the returned
seq are in order of decreasing subsequence count.
"
[n-length-subseqs]
(if (empty? (first n-length-subseqs))
nil
(cons n-length-subseqs
(lazy-seq
(subseqs-by-count (->> n-length-subseqs
; There are just two (n-1)-length subseqs.
; for each n-length subseq. Make them.
(mapcat (juxt butlast next))
; Finally, remove duplicates.
set))))))
(defn common-subseqs
"Returns a lazy seq of sets of subsequences common to all the given
seqables. (Args. don't have to be strings.) Each set contains subsequences
of the same count, and the sets are returned in decreasing order of these
counts. None of the sets are empty.
"
[& strs]
(let [min-cnt (apply min (map count strs))
shorten (fn [seq-of-sets]
; Remove extra sets from the front of arg. to make count
; min-cnt. We use the fact that the count of arg. is just
; the count of any sequence in its first set. That way, we
; need not create ever-shorter subsequences until needed.
(-> seq-of-sets
first
first
count
(- min-cnt)
(drop seq-of-sets)))]
(->> strs
(map seq) ; Ensure input consists of seqs, not strings.
(map (partial conj #{})) ; Put each seq (former string) into to a set.
(map subseqs-by-count) ; Now a seq of seq of sets of sub-seqs.
(map shorten) ; Only need to compare w/ shortest.
(apply map intersection) ; Seq of sets of common seqs, by decr. count.
(filter not-empty)))) ; Remove empties (indicate no commons seqs).
(def maximal-common-subseqs
"Returns a set of all commmon subsequences of the given sequence arguments
that have the greatest count.
"
(comp first common-subseqs))
(def maximal-common-substrings
"Returns a sequence of all common substrings of the given string arguments
that have the greatest count.
"
(comp
(partial map (partial apply str))
maximal-common-subseqs))
(defn maximal-common-substrings-ignoring-case
[& strs]
(->> strs
(map upper-case)
(apply maximal-common-substrings)))