Ruby Quiz <james / grayproductions.net> writes:

> My thanks to all you pangram hunters.  As always you taught me
> clever new tricks in optimization.

For the record, this is how I found the shortest possible solution:

1) Look at the words.  Recognize "zcat" needs to be in there, and
   remove it from the list.

2) Download dance.w[1] from Donald E. Knuth, tangle and compile.

    [1]: http://www-cs-faculty.stanford.edu/~knuth/programs/dance.w

3) Write a small program prep.rb to preprocess the words for the
   expected input format:

    words = %w{
    admin alias ar asa at awk basename batch bc bg c99 cal cat cd cflow
    chgrp chmod chown cksum cmp comm command compress cp crontab csplit
    ctags cut cxref date dd delta df diff dirname du echo ed env ex expand
    expr false fc fg file find fold fort77 fuser gencat get getconf getopts
    grep hash head iconv id ipcrm ipcs jobs join kill lex link ln locale
    localedef logger logname lp ls m4 mailx make man mesg mkdir mkfifo more
    mv newgrp nice nl nm nohup od paste patch pathchk pax pr printf prs ps
    pwd qalter qdel qhold qmove qmsg qrerun qrls qselect qsig qstat qsub
    read renice rm rmdel rmdir sact sccs sed sh sleep sort split strings
    strip stty tabs tail talk tee test time touch tput tr true tsort tty
    type ulimit umask unalias uname uncompress unexpand unget uniq unlink
    uucp uudecode uuencode uustat uux val vi wait wc what who write xargs
    yacc zcat
    }
    
    #     ----------------- required -----------------|-- optional --
    puts "b d e f g h i j k l m n o p q r s u v w x y | z c a t 4 7 9"
    words.each { |w|
      puts w.split(//).join(" ")
    }

4) Run it like this: 

    $ ruby prep.rb | dance verbose
    
    1:
     j o b s (1 of 2)
     y t t (1 of 3)
     h g r p c (1 of -2)
     e x l (5 of -3)
     w k a (1 of -2)
     i q u n (4 of -2)
     f d (1 of 0)
     m v (2 of 0)
    2:
     j o i n (2 of 2)
     v m (1 of 2)
     k a w (1 of 3)
     h g r p c (1 of 2)
     b q s u (1 of 1)
     f d (1 of 1)
     l e x (1 of 1)
     y t t (1 of 1)
    3:
     j o i n (2 of 2)
     v m (1 of 2)
     k a w (1 of 3)
     h s (2 of 2)
     q d e l (1 of 1)
     y t t (1 of 1)
     r p (1 of 0)
     b c (1 of 2)
     f g (1 of 1)
     u u x (1 of 2)
    4:
     j o i n (2 of 2)
     v m (1 of 2)
     k a w (1 of 3)
     h s (2 of 2)
     q d e l (1 of 1)
     y t t (1 of 1)
     r p (1 of 0)
     b c (1 of 2)
     f g (1 of 1)
     u x u
    5:
     j o i n (2 of 2)
     v m (1 of 2)
     k a w (1 of 3)
     h s (2 of 2)
     q d e l (1 of 1)
     y t t (1 of 1)
     r p (1 of 0)
     b g (2 of 2)
     f c (1 of 1)
     u u x (1 of 3)
    6:
     j o i n (2 of 2)
     v m (1 of 2)
     k a w (1 of 3)
     h s (2 of 2)
     q d e l (1 of 1)
     y t t (1 of 1)
     r p (1 of 0)
     b g (2 of 2)
     f c (1 of 1)
     u x u
    Altogether 6 solutions, after 3056 updates.
         0     0     1     1     0     0       2 nodes, 597 updates
         1     1     0     1     0     0       3 nodes, 663 updates
         3     0     1     0     0     0       4 nodes, 663 updates
         0     2     0     0     0     0       2 nodes, 355 updates
         0     2     0     0     0     0       2 nodes, 257 updates
         2     1     0     0     0     0       3 nodes, 263 updates
         1     1     1     0     0     0       3 nodes, 139 updates
         3     2     0     0     0     0       5 nodes, 78 updates
         0     0     0     0     1     1       2 nodes, 19 updates
         4     0     0     0     0     0       4 nodes, 22 updates
    Total 31 nodes.

5) Look at the shortest solutions (1 and 2), and write them down as
   unix commands.

6) Since dance.w uses DLX to find optimal matches, these are the
   shortest solution (but not with least possible words, as I first
   assumed, too).  We needed to remove "zcat", because there is no way
   with it to have an optimal match (i.e. every letter only once).

    "awk chgrp df jobs lex mv tty uniq zcat"
    "awk chgrp df join lex mv tty qsub zcat"

Enjoy, "and know thy tools",
-- 
Christian Neukirchen  <chneukirchen / gmail.com>  http://chneukirchen.org