        (str/split-lines )
        (map str/trim ) ))
 
-(def words-by-length  
+(def tst-words [ 
+  "is" "at" "by" "up"
+  "act" "add" "ace" "and" "ask" "abe" "ads"
+  "bad" "bug" "bed" "bet"  "big" "bit"
+  "cat" "car" "can" "cob" "con" "cop" "cup" 
+  "work" "love" "hate" "jobs" "able" "ball" ] )
+
+(defn words-by-length  
   "Maps word length to word values.  Each key is a word length. Each value is a collection
   of all words of that length.  Keys are absent if no words of that length are present."
-  (group-by count all-words) )
+  [word-seq]
+  (group-by count word-seq) )
 
-(def max-word-length 
-  "The maximum length of any word."
-  (apply max (keys words-by-length)) )
+(defn max-word-length 
+  "The maximum length of any word in a sequence."
+  [word-seq]
+  (apply max (map count word-seq) ))
 
 (defn to-word-array 
   "Returns all words of the specified length as a 2D array (vector of vectors).
   First index selects a given word, 2nd index selects chars from that word."
-  [word-length]
+  [word-seq word-length]
   { :pre  [ (integer? word-length) ]
     :post [ (vector? %) ] }
   (vec
-    (map vec (words-by-length word-length)) ))
+    (map vec ((words-by-length word-seq) word-length)) ))
 
-(defn get-array-column
+(defn num-rows
+  "Given a 2D array (vector of vectors), return the number of rows (1st dimension)."
+  [word-array]
+  { :pre  [ (vector? word-array) ]
+    :post [] }
+  (count word-array) )
+
+(defn num-cols
+  "Given a 2D array (vector of vectors), return the number of columns (2nd dimension)."
+  [word-array]
+  { :pre  [ (vector?  word-array) 
+            (vector? (word-array 0)) ]
+    :post [] }
+  (count (word-array 0)) )
+
+(defn get-array-col
   "Given a 2D array (vector of vectors), return a vector of elements 
   from the specified column."
   [word-array col-idx]

             {\a 1 \b 2 \c 3} ))
)

(defn words-of-length 
  "Returns a seq of words of the specified length."
  [word-length]
  { :pre  [ (integer? word-length) ]
    :post [ ] }
  (get words-by-length word-length [] ) )

; (def data-map
;   "A map of data keyed by word length"
;   (doseq [curr-len (range 4 (inc 4)) ]
;     (apply merge-with + 
;       (map frequencies (words-of-length curr-len)) )))

(defn main []
  (println "main: enter")

    :post [ (vector? %) ] }
  (word-array row-idx) )

(defn words-of-length 
  "Returns a seq of words of the specified length."
  [word-length]
  { :pre  [ (integer? word-length) ]
    :post [ (vector? %) ] }
  (vec
    (get words-by-length word-length [] ) ))

(defn freqs-by-col
  "For each column of a 2D array, computes an element frequency map. Returns as 
  a vector indexed by column."
  [word-array]
  { :pre  [ (vector? word-array)
            (< 0 (num-rows word-array) )
            (< 0 (num-cols word-array) ) ] 
    :post [ (vector? %) ] }
  (vec
    (for [idx (range 0 (inc (num-cols word-array) )) ]
      (frequencies (get-array-col idx)) )))


(defn run-tests []
  ; Manipulation of strings/vectors/character seq's
  (assert (= (vec "abcd")                [\a \b \c \d] ))
  (assert (= (str/join  (vec "abcd"))    "abcd" ))
  (assert (= (apply str (vec "abcd"))    "abcd" ))

  ; Test array slicing functions
  (let [ tstArr [ [:a :b :c] [1 2 3] [\a \b \c]] ]
    (assert (= (get-array-row tstArr 0) [:a :b :c] ))
    (assert (= (get-array-row tstArr 1) [ 1  2  3] ))
    (assert (= (get-array-row tstArr 2) [\a \b \c] ))
    (assert (= (get-array-col tstArr 0) [:a  1 \a] ))
    (assert (= (get-array-col tstArr 1) [:b  2 \b] ))
    (assert (= (get-array-col tstArr 2) [:c  3 \c] ))
  )

  ; Use of (frequencies...) and (merge-with...)
