(use 'clojure.contrib.combinatorics
     'clojure.contrib.str-utils)

(defn anagrams [xs]
  (map #(str-join "" %) (distinct (permutations xs))))

Of course, the real meat is in the permutations function. The
implementation in the combinatorics library is a bit complicated.
Here's something simpler (and slower):

(defn splittings [xs]
  (lazy-seq
   (cons [() xs]
         (when (seq xs)
           (map (fn [[left right]]
                  [(cons (first xs) left) right])
                (splittings (rest xs)))))))

(defn permutations [xs]
  (if (seq xs)
    (for [perm (permutations (rest xs))
          [left right] (splittings perm)]
      (concat left [(first xs)] right))
    [()]))

On Mon, Apr 19, 2010 at 8:20 AM, verec
<[email protected]> wrote:
> I have two problems with the following code.
> First, I have this `tos' business (to-string) because:
> user=> (first "abc")
> \a
> user=> (rest "abc")
> (\b \c)
> Since I wanted to get strings out of strings, a character or a
> collection is no good.
>
> Second, I ended-up having to use a mutable atom `res' because I
> couldn't figure out how to do it otherwise.
>
> Any pointer on how to tackle either or both problems welcome.
>
> (ns word-play)
>
> (defn rotate
>  "Take a collection and left rotates it n steps.
>  If n is negative, the collection is rotated right.
>  Executes in O(n) time."
>  ([coll]
>    (rotate 1 coll))
>  ([n coll]
>    (let [c (count coll)]
>      (take c (drop (mod n c) (cycle coll))))))
>
> (defn all-rotations [word]
>  "all rots"
>  (take (count (str word)) (cycle (iterate rotate (str word)))))
>
> (defn anagram [word]
>  "To generate all anagrams of a given string of length n, the most
>  obvious solution is to consider all n rotations of the string one
>  by one, and for each such rotation, concatenate its first character
>  with each of the anagrams of the new string composed of all but its
>  first character."
>  (cond
>     (= (count word) 0) '("")
>     (= (count word) 1) (list word)
>     true
>      (let [all (all-rotations word)
>            tos #(str (reduce str %))
>            wst (map tos all)
>            res (atom "")]
>        (doseq [w wst]
>          (let [s (str w)
>                f (str (first (str s)))
>                n (str (tos (next (str s))))
>                j #(str f (tos %))
>                a (ana3 n)
>                r (map j a)]
>            (swap! res concat r)))
>       �...@res)))
>
> user=> (anagram "1")
> ("1")
> user=> (anagram "12")
> ("12" "21")
> user=> (anagram "123")
> ("123" "132" "231" "213" "312" "321")
> user=> (anagram "lisp")
> ("lisp" "lips" "lspi" "lsip" "lpis" "lpsi" "ispl" "islp" "ipls" "ipsl"
> "ilsp" "ilps" "spli" "spil" "slip" "slpi" "sipl" "silp" "plis" "plsi"
> "pisl" "pils" "psli" "psil")
> user=>
>
> --
> 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

-- 
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

Reply via email to