I have a file LIST that has a sequence of characters per line. Each line is labeled with a category, i.e. “C”. Example:
C: w r t y i o p s d f g h j k l z b n m
V: a e i o u
E: n m ng
I want to print every combination of C, V and E (or maybe just C and V, C and E, etc.) using doseq, but generically as I won’t know the nested collections at compile time.
I.e.
"CV" [x y] (str x y )
"CVE" [x y z] (str x y z)
"CVCV" [x y z a] (str x y z a)
My code word-generator.clj
(ns word-generator )
(use 'clojure.string)
(import 'java.io.File)
(use 'clojure.java.io)
(defn get-lines [fname]
(with-open [r (reader fname)]
(doall (line-seq r))))
(defn get-list [x lines]
(first (remove nil?
(for [num (range (count lines)) ]
(if (= (first(split (nth lines num) #"\s+")) x)
(rest(split (nth lines num) #"\s+")))))))
(def sounds(get-lines "LIST")) ;; get the list
(def C (get-list "C:" sounds)) ;; map consonants
(def V (get-list "V:" sounds)) ;; map vowels
(def E (get-list "E:" sounds)) ;; map end consonants
(def LI "CVE") ;; word structure
(defn word-runner[carry args depth]
(doseq [x C y V z E] (println (str x y z)))) ;; iterate and make the words
(defn runner[]
( (print "enter arg list: ")
(def INPUT (read-line))
(word-runner "" INPUT 0)))
How can I implement word-runner so that doseq does a nested loop over all sequences of characters found in the file – but without knowing the number of lines in the file at compile-time?
This is actually a problem of combinatorics, not so much looping. Use the
cartesian-productfunction from the math.combinatorics library to solve your problem.