Perl 'Expert' Quiz-of-the-Week #11

Mark Jason Dominus <[email protected]> Fri, 07 Feb 2003 12:03:40 -0500
Newsgroups gmane.comp.lang.perl.qotw.quiz-of-the-week
Organization Plover Systems
Message-ID <[email protected]>

IMPORTANT: Please do not post solutions, hints, or other spoilers
        until at least 60 hours after the date of this message.
        Thanks.

IMPORTANTE: Por favor, no enviéis soluciones, pistas, o cualquier otra
        cosa que pueda echar a perder la resolución del problema hasta
        que hayan pasado por lo menos 60 horas desde el envío de este
        mensaje. Gracias.

IMPORTANT: S'il vous plaît, attendez au minimum 60 heures après la
        date de ce message avant de poster solutions, indices ou autres
        révélations. Merci.

WICHTIG: Bitte schicken Sie keine Lösungen, Tipps oder Hinweise für
        diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser
        Mail. Danke.

BELANGRIJK: Stuur aub geen oplossingen, hints of andere tips in de
        eerste 60 uur na het verzendingstijdstip van dit
        bericht. Waarvoor dank.

VNIMANIE: Pozhalujsta ne shlite reshenija, nameki na reshenija, i
        voobshe lyubye podskazki v techenie po krajnej mere 60 chasov
        ot daty etogo soobshenija.  Spasibo.

Qing3 Zhu4Yi4: Qing3 Ning2 Deng3Dao4 Jie1Dao4 Ben3 Xin4Xi2 Zhi1Hou4 60
        Xiao3Shi2, Zai4 Fa1Biao3 Jie3Da2, Ti2Shi4, Huo4 Qi2Ta1 Hui4
        Xie4Lou4 Da2An4 De5 Jian4Yi4.  Xie4Xie4.


----------------------------------------------------------------

A frequently-asked question is: "How do I tell whether a string is a
number?"  The reason there's no simple answer to this question is that
"number" has many different meanings, and you can't answer until you
find out which one was meant. 

The people who ask this question, however, don't realize this.  They
think you're just being obstructionist if you tell them you need to
find out what they mean by 'number'.  Because, of course, *everyone*
knows what a 'number' is.

One approach that has worked well for me in the past has been to play
twenty questions with the querent.  "Is 0123 a number?"  "No."  "Is
6.5 a number?"  "Yes."  "Is -6.5 a number?"  "Why are you wasting my
time with these silly questions?  Of course it is."  And so on.

The next time I'll play the game with a different person, and I'll ask
if "-6.5" is a number, and they'll reply "Why are you wasting my time
with these silly questions?  Of course it isn't."

perlfaq4 covers a few special cases, but not all the cases that people
want.  Regexp::Common is more flexible.

But it's always seemed to me that it might be more effective to write
a program that would play the twenty questions game, and then produce
the appropriate regexp at the end.  The twenty questions game, of
course, is just the guess-the-animal program from last week.
So if the program fails to produce the desired regex, the user should
be able to come back and say "That was not the regex I wanted."

     C:   "What is an example string that was not correctly identified
           by that regex?"

     U:   "6.250"

     C:   "Would you consider that a number?"

     U:   "No."

     C:   (Checks to make sure that 6.250 does indeed match the regex.)
          "Thanks.  Do you know a regex that does do what you want?"

And then, one of the following might ensue:

     U:   /^M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/

     C:  "WARNING: You told me that 0 was a number, but that regex
          does not match 0!"

or

     U:   /^M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/

     C:  "WARNING: You told me that I was not a number, but that regex
          matches I!"

or

     U:   /^M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$/

     C:  "Thanks.  I'll try to remember that for next time."

         (The program now commits the regex to a database; if a human
         expert concurs later, it can be added to the program's
         knowledge base in guess-the-animal style.)

or

     U:  I don't know.

     C:  "I'll forward your question to a human expert.  Thanks for playing!"


It doesn't have to go exactly like this, of course.  It's just the
first thing I thought of.  

One reason this is an expert quiz is that it seems pretty clear that
using pure guess-the-animal style is not really tractible.  There are
a lot of different ways to compose numerals:

        decimal / octal / hexadecimal 
        no leading sign allowed / optional leading - / 
                optional leading + or - / leading + or - required
        leading zeroes allowed / not allowed
        decimal point allowed / not allowed
        scientific notation allowed / not allowed
        trailing zeroes after decimal point allowed / not allowed

Imagine a pure guess-the-animal style program to make this sort of
distinction.  Let's suppose that the first few questions are directed
towards finding out what sort of leading sign symbol might be
required.  Then the notional data tree for the program will have four
main branches.  In one branch, the regexes will all begin with
/^[+-].../.  In another branch, they will all begin with /^[+-]?.../.
In the other two branches, all the regexes will begin with /^-?.../
and /^.../, respectively,  Other than that, however, these four
branches will be extremely similar, and will have almost exactly the
same questions in them!  So it might make sense to abandon the
guess-the-animal approach at least part of the time, and to generate
the regexes algorithmically.

I also imagined that a program like this might be most useful as a CGI
application.  Then beginners asking how to tell if the user entered a
number could be directed to the web page for the application.