Hi Meikel, Nicolas, and Justin, Thank you for the great feedback! I learned a lot. I was puzzled about (update-in (update-in)) and after doing that the -> operator makes a lot of sense. The reduce is clever and fits nicely as well.
I dropped the function that read in the lines of the file and used read-lines instead. Below is what I put together after the feedback. Thanks, Damon PS- I was mistaken before. The first version was taking over a minute. This version takes about 15s. (ns clojure.example.anagrams (:require clojure.contrib.duck-streams) (:gen-class)) (defn str-sort[string] (when string (apply str (sort string)))) (defn str-to-lower[string] (when string (.toLowerCase string))) (defn anagram-add[anagrams akey word] (if (contains? anagrams akey) (-> anagrams (update-in [akey :count] inc) (update-in [akey :words] conj word)) (assoc anagrams akey {:count 1 :words [word]}))) (def normalise (comp str-to-lower str-sort)) (defn build-anagrams[words] (reduce #(anagram-add %1 (normalise %2) %2) {} words)) (defn print-anagram[v] (println (str (:count (second v)) " " (first v) ": " (:words (second v))))) (defn print-anagrams[ana] (doseq [v ana] (print-anagram v))) (defn anagram-key[elem] (- (:count (second elem)))) ;(def *words* (f-to-seq "/usr/share/dict/web2")) ;(def *anagrams* (sort-by anagram-key (build-anagrams *words*))) ;(print-anagrams (take 10 *anagrams*)) (defn -main[file] (time (print-anagrams (take 10 (sort-by anagram-key (build-anagrams (clojure.contrib.duck-streams/read-lines file))))))) On Aug 19, 5:41 am, Meikel Brandmeyer <m...@kotka.de> wrote: > Hi, > > here my turn. Comments inline. Hope this helps. > > Sincerely > Meikel > > (defn f-to-seq > [file] > (with-open [rdr (java.io.BufferedReader. > (java.io.FileReader. file))] > (doall (line-seq rdr)))) > ; Yes. doall is required here. Alternatively you can wrap the whole > thing > ; in the with-open. Then you can process also larger files without > keeping > ; all data in memory. YMMV. > > (defn str-sort > [string] > (when string > (apply str (sort string)))) > ; One can also skip the when here. Then nil input returns an empty > string. > ; Whether that is better depends on the usage of the return value. > YMMV. > ; (if (nil? x) x ...) is usually written as (when x ...). > > (defn str-to-lower > [string] > (when string > (.toLowerCase string))) > > (defn anagram-add > [anagrams akey word] > (if (contains? anagrams akey) > (-> anagrams > (update-in [akey :count] inc) > (update-in [akey :words] conj word)) > (assoc anagrams akey {:count 1 :words [word]}))) > ; I would prefer vectors over lists to store stuff. You get nice > ; things for free, like O(1) appending, O(1) reverse, O(1) random > ; access, ... > > (defn word > [s] > (first s)) > ; or: (def word first) > ; not needed for my solution > > (def normalise (comp str-to-lower str-sort)) > > (defn build-anagrams > [words] > (reduce #(anagram-add %1 (normalise %2) %2) {} words)) > ; Looping with an accumulator, just returning the latter when the > ; input is exhausted cries for reduce. > > (defn print-anagram > [v] > (println (str (:count (second v)) " " (first v) ": " (:words (second > v))))) > ; one could use destructuring to access things. > > (defn print-anagram > [anagram] > (let [[normal-form {:keys [count words]}] anagram] > (println (str count " " normal-form ": " words)))) > > (defn print-anagrams > [ana] > (doseq [v ana] > (print-anagram v))) > ; more descriptive names would be good, I guess > > (defn anagram-key > [elem] > (- (:count (second elem)))) > ; the minus should take care of the reverse? > > (def *words* (f-to-seq "/usr/share/dict/web2")) > (def *anagrams* (sort-by anagram-key (build-anagrams *words*))) > (print-anagrams (take 10 *anagrams*)) -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en