Comments requested on noob code

From: John Landahl (john_at_landahl.org)
Date: 01/26/05


Date: Wed, 26 Jan 2005 18:58:07 GMT

Hi, all. I'm pretty much a complete beginner at Lisp (though not a
beginning programmer), and would appreciate some feedback from experienced
Lispers on a tiny bit of code.

The aim is to use a dictionary file (one word per line,
e.g. /usr/share/dict/words) to determine how many valid words can be made
from a "rack" of letters (a la Scrabble). Here's a sample run:

(time (find-in-file "/usr/share/dict/words" "struoi"))
Evaluation took:
     0.303 seconds of real time
     0.26596 seconds of user run time
     0.025996 seconds of system run time
     0 page faults and
     18,410,256 bytes consed.
("" "I" "Io" "Ir" "It" "Ito" "O" "Os" "Otis" "R" "Rio" "Rios" "Ru" "S" "Si"
 "Sr" "St" "Stu" "Sui" "T" "Ti" "U" "Ur" "Uris" "i" "is" "it" "its" "o" "or"
 "our" "ours" "oust" "out" "outs" "r" "riot" "riots" "rot" "rots" "rout"
 "routs" "rs" "rust" "rut" "ruts" "s" "sir" "sit" "so" "sort" "sot" "sour"
 "stir" "suit" "suitor" "t" "ti" "to" "tor" "tors" "torsi" "torus" "tour"
 "tours" "trio" "trios" "ts" "u" "us")

The code is included below. Some specific questions I have:

  1) The speed is quite acceptable, but quite a bit of memory is
     being used. This is no doubt because of the way match-letters
     is written, and so:
  2) I'm using recursion with first/rest and remove in match-letters;
     is there a better way to do this?
  3) I'm using "loop for ... across ..." to split a string into a list
     of chars. Is this acceptable, or is there a more idiomatic way to
     do this?
  4) match-word is an intermediary function used for sanity checking
     and for converting the string to a char list. Is there a cleaner
     way to do this within find-in-file's loop?
  5) Would type declarations help in way?
  6) SLIME question: why does SLIME indent slightly differently when
     editing a file versus indenting in the REPL? Specifically, the
     else clauses are backdented two spaces when editing a file, but
     are lined up with the main clause in the REPL.

Any and all comments/suggestions are welcome. I'm especially interested in
learning the most idiomatic way to do these things in Lisp. Thanks in
advance. Code follows:

(defun match-letters (letters rack)
  "Determine whether 'letters' (a list of chars) can be created from choices
   in 'rack' (also a list of chars)."
  (if (null letters)
      t
    (let ((letter (first letters)))
      (if (find letter rack)
   (match-letters (rest letters) (remove letter rack :count 1))
        nil))))

(defun match-word (word rack-letters)
  (if (or (null word))
      nil
    (let ((word-letters (loop for l across word
         collect (char-downcase l))))
      (match-letters word-letters rack-letters))))

(defun find-in-file (file-name rack)
  (let ((rack-letters (loop for l across rack
       collect (char-downcase l))))
    (with-open-file (in file-name)
      (loop for word = (read-line in nil)
     while word
     when (match-word word rack-letters)
     collect word))))



Relevant Pages

  • Re: SMS compression ?
    ... I live in Russia and here SMS are only 70 chars short for Russian ... Big letters, latin letters, digits and special chars are accessed by ... Compress first all 8-th bits, ...
    (comp.compression)
  • Re: Letter to Sis...again
    ... after which my rack was empty. ... words of seven letters). ... but asked if he knew how to play. ... The player was Karl Khoshnaw, ...
    (alt.usage.english)
  • Re: Bingo probability in Scrabble
    ... distribution of letters in Scrabble. ... that it is an easy calculation, ... the tiles on one's rack being able to produce a 7-letter word. ...
    (rec.puzzles)
  • Re: is this a good way to find anagrams?
    ... > letters in your given word. ... please help me make my ruby more ruby-like. ... >> def rodolfo(secret_word, rack) ...
    (comp.lang.ruby)
  • Re: Utility to generate test data
    ... random hexadecimal numerals 0..F ... random capital letters A..Z ... fixed chars ...
    (borland.public.delphi.thirdpartytools.general)