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