I believe duck-streams is deprecated since clojure 1.2. You may want to consider bringing back f-to-seq, which can be simplified slightly using reader from clojure.java.io:
(ns clojure.example.anagrams (:use [clojure.java.io :only (reader)]) (:gen-class)) (defn f-to-seq [file] (with-open [rdr (reader file)] (doall (line-seq rdr)))) On Aug 19, 10:39 pm, Damon Snyder <drsny...@gmail.com> wrote: > 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