[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[FWP] Golf challenge: Scoring a word list



As part of my "cheating hangman" implementation in Haskell (see link
at end of post), I use a scoring heuristic to define how much cheating
opportunity a list of words provides.  The heuristic considers word
lists to be better the longer they are (the more words they have in
them) and the less repetitious the letters within its words are.  So,
given the three lists A, B, and C below,

                  A            B            C
                
                angles       angles       makers
                stones       fluffs       primal
                             stones       vulcan

              (score=11)   (score=15)   (score=18)

B scores more highly than A because it has more words, and C more
highly than B because its words have more unique letters than B's
words do.  That is, "makers", "primal", and "vulcan" each have six
unique letters, thus C's score is their sum, 18.  In list B, "fluffs"
has two repetitions and "stones" has one, costing B three points; its
score is only 15.

The heuristic also takes into account the guesses that the player has
made.  If the player just guessed the letter "s", for example, then
none of the "s" letters in the lists help the dealer.  Then the lists
would be scored as if all their "s" letters were removed, giving new
scores of 9, 12, and 17, respectively.

Ignoring for the moment whether this is a good scoring heuristic, the
implementation of it in my game is surprisingly brief:

    cscore :: Guesses -> Words -> Int
    cscore gs = sum . map (length.group.sort.filter(`notElem`gs))

The cscore function takes two arguments -- a list of guessed letters
and a list of words to score -- and returns the score as an integer.
It computes the score as follows:

    For each word in the list,
        remove the guessed letters,         
        sort the remaining letters,
        group the sorted letters (e.g., "aabccc" -> ["aa","b","ccc"]),
        count the number of groups.
    Add up all the counts across the word list to yield the score.

Thus the expression

    cscore "as" ["makers","primal","vulcan"]

evaluates to 14.


THE GOLF CHALLENGE

Write the shortest Perl one-liner that reads a list of words on
standard input and prints its score, given that the letters in
$ARGV[0] have been guessed.  For example, if the file "test" contains:

makers
primal
vulcan

You should be able to enter the following command line

    perl [MAGIC STUFF HERE] "as" <test

and see "14" as output.

I've got my golf entry ready (73 chars), but I'll wait a while before
posting it to avoid tainting the idea pool.

Well, there's the challenge.  Have at it!

Cheers,
Tom

P.S.  For more on my cheating hangman implementation:
      http://www.ellium.com/~thor/hangman/

==== Want to unsubscribe from Fun With Perl?  Well, if you insist...
==== Send email to <fwp-request@technofile.org> with message _body_
====   unsubscribe