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

Reply via email to