Scrabble
February 22, 2019
I was feeling silly on Thursday evening, when I wrote this exercise, and came up with this shell script:
rack='Q O F T H E A' while true do for word in $(shuf -ze $rack) do for n in 2 3 4 5 6 7 do if $(grep -qi ^$(printf "%${n}.${n}s\n" $word)$ /usr/share/dict/words) then printf "%${n}.${n}s\n" $word fi done done done
The shuf
program produces a random permutation of its input, the loop on printf
produces each 2 to 7 letter prefix of the permutation, and grep
determines if the word is in its dictionary. There is no guarantee that all permutations are eventually considered, it is likely that there will be duplicates, and making an entire pass through the dictionary for each potential word is ridiculously expensive. Here is some of the output, limited to words of 4 or more letters by removing 2 and 3 from the loop on n and with Q replaced by S:
HOES THEA HEFT OAFS SATE HEAT HOSE SAFE SATE HOSE SEAT HEAT SOFA FATS FEAST ETHOS HOSE HOSEA SOFA SHAFT HOSE OATH HATS SHAT HAFT HAFTS SATE SAFE SOFT FOES
You can see the program at https://ideone.com/fjS7j7, but can’t run it because there is no dictionary.
@programmingpraxis: I see the letter S popping up in your results. Your code on ideone has an extra S.
In Python. All words without the S are printed
Assumes letters can be used multiple times
Python solution, sort letters and do an element by element comparison on the sorted letters:
A Haskell version using the dictionary on a Mac. (The letter ‘q’ doesn’t appear in the output.)
And here’s the same thing using egrep.
Then I saw @Globules elegant solution and realised that mine could be greatly simplified if I just tweaked the regexp.
and use it like this:
👏 to @Globules
This is supposed to be Scrabble so letters can’t be used more than once.
Here is a more Scrabble-conforming version, where each letter is used at most once.
Here’s a trie-based solution – read the set of words into a trie (using the sorted letters of each word for the trie entries, rather than the word itself). Then we can find subsets of the given letter multiset reasonably efficiently. Since it’s Scrabble, just consider all-lowercase words (no proper nouns allowed).
Common Lisp:
Common Lisp:
[sourcecode lang="lisp"]
(defun is-scrabble-word (word letters)
(and (<= 2 (length word) 7)
(every #'(lambda (c) (find c letters)) word)))
(defun filter-dictionary (path letters)
(with-open-file (in path)
(loop for line = (read-line in nil nil)
while line
when (is-scrabble-word (string-upcase line) letters) collect line)))
(defun print-scrabble ()
(format t “~{~a ~}” (filter-dictionary “/usr/share/dict/words” “QOFTHEA”)))
Here’s a solution in Python:
Output: