Listing 1. findwords.sh<remark
role="output-file">11935l1.qrk</remark></title>

<programlisting>
<![CDATA[
#!/bin/sh

# Findwords -- given a set of letters, try to find all the words you can
# spell

dictionary="/Users/taylor/Documents/Linux Journal/dictionary.txt"

testwords=$(mktemp /tmp/findwords.XXXXXX) || exit 1

if [ -z "$1" ] ; then
  echo "Usage: findwords [sequence of letters]"
  exit 0
fi

if [ "$1" = "-f" ] ; then
  showfails=1
  shift
fi

## PART ONE: make the regular expression

length="$(echo "$1" | wc -c)"
minlength=$(( $length - 4 ))    # we can ignore a max of 2 letters

if [ $minlength -lt 3 ] ; then
  echo "Error: sequence must be at least 5 letters long"
  exit 0
fi

unique="$(echo $1 | sed 's/./&\
/g' | tr '[[:upper:]]' '[[:lower:]]' | sort | uniq | fmt | \
tr -C -d '[[:alpha:]]')"

while [ $minlength -lt $length ]
do
  regex="^[$unique]{$minlength}$"

  if [ $verbose ] ; then
    echo "Raw word list of length $minlength for letterset $unique:"
    grep -E $regex "$dictionary" | tee -a $testwords
  else
    grep -E $regex "$dictionary" >> $testwords
  fi
  minlength="$(( $minlength + 1 ))"
done

## PART TWO: sort letters for validity filter

pattern="$(echo $1 | sed 's/./&\
/g' | tr '[[:upper:]]' '[[:lower:]]' | sort | fmt | sed 's/ //g')"

for word in $( cat $testwords )
do
  # echo "checking $word for validity"

  simplified="$(echo $word | sed 's/./&\
/g' | tr '[[:upper:]]' '[[:lower:]]' | sort | fmt | sed 's/ //g')"

  ## PART THREE: do all letters of the word appear in the pattern
  #              once and exactly once? Easy way: loop through and
  #              remove each letter as used, then compare end states

  indx=1
  failed=0
  before=$pattern

  while [ $indx -lt ${#simplified} ]
  do
    ltr=${simplified:$indx:1}
    after=$(echo $before | sed "s/$ltr/-/")
    if [ $before = $after ] ; then
      # nothing changed, so we don't have that
      # letter available any more
      if [ $showfails ] ; then
        echo "FAILURE: came close, but can't make $word"
      fi
      failed=1
    else
     before=$after
    fi

    indx=$(( $indx + 1 ))
  done

  if [ $failed -eq 0 ] ; then
    echo "SUCCESS: You can make the word $word"
  fi

done

/bin/rm -f $testwords

exit 0