     :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-column tstArr 0) [:a  1 \a] ))
-    (assert (= (get-array-column tstArr 1) [:b  2 \b] ))
-    (assert (= (get-array-column tstArr 2) [:c  3 \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...)

             {\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")

       (str/split-lines )
       (map str/trim ) ))

(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."
  [word-seq]
  (group-by count word-seq) )

(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-seq word-length]
  { :pre  [ (integer? word-length) ]
    :post [ (vector? %) ] }
  (vec
    (map vec ((words-by-length word-seq) word-length)) ))

(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]
