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 <[email protected]> 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 <[email protected]> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en