Idiomatic letterpress cheater I need some guidance on making the following code more idiomatic:

(ns cheaterpress.algorithm
  (:use [clojure.string :only [split lower-case]])
  (:use [clojure.test]))

(def words (split (slurp "words") #"\s"))

(defn string-to-letter-hash [string]
  (loop [letters (seq string) letter-hash {}]
    (if (empty? letters)
      letter-hash
      (let [letter (first letters) letter-freq (get letter-hash letter 0)]
        (recur (rest letters) (assoc letter-hash letter (inc letter-freq)))))))

(defn can-play [word letters index]
  (loop [letters letters index index]
    (if (and (= (inc index) (count word)) (not (= 1 (count word))))
      true
      (let [letter (get word index) frequency (get letters letter 0)]
        (when (not (= 0 frequency))
          (recur (assoc letters letter (dec frequency)) (inc index)))))))

(println 
  (time
    (count (doall (filter #(can-play % (string-to-letter-hash "abcdefghijklmnopqrstuvxyz") 0) (map lower-case words))))))


string-to-letter-hash takes a string and returns a map with the letter frequencies, e.g.:

(string-to-letter-hash "hello")
;=&gt; {\h 1 \e 1 \l 2 \o 1}


can-play takes a letter frequency hash and a word, and then it finds out if it can make the word from the letters in the hash map. If it can, it returns true, otherwise, nil.

(can-play "hello" {\h 1 \e 1 \l 2 \o 1} 0)
;=&gt; true
(can-play "lol" {\h 1 \e 1 \l 2 \o 1} 0)
;=&gt; true
(can-play "hello world" {\h 1 \e 1 \l 2 \o 1} 0)
;=&gt; nil


The last bit of code in my script basically gets all the words in a file and finds which of them can be played according to the can-play function.
Well there is a standard library function: frequences :)

user&gt; (doc frequencies)
-------------------------
clojure.core/frequencies
([coll])
  Returns a map from distinct items in coll to the number of times
  they appear.


Since in Clojure many many types can be converted to sequences, frequencies will work on many types, including strings. In Clojure you can get an amazing amount of work done simply by using the sequence library. So your string-to-letter-hash is actually just an example of frequences.

For your can-play: the same type of thinking applies. Try to resist your first impulse of writing a loop. The Clojure library functions will almost always do the job - the thing that requires training is knowing the library well enough to find a good way to compose the functions.

(defn can-play? [word freqs]
  (every? #(&gt;= % 0) (vals (merge-with - freqs (frequencies word)))))


(updated to comment version: https://gist.github.com/4105644)