Front page | perl.fwp |
Postings from January 2002
Keith's SUAP explanation
Thread Previous
|
Thread Next
From:
Keith C. Ivey
Date:
January 28, 2002 20:56
Subject:
Keith's SUAP explanation
Message ID:
3C55E56F.31124.1FCFFFD0@localhost
Andrew.Savige@ir.com wrote:
> So as soon as you can after the game has finished, I would like
> the golf "artists" to prepare a little description of your
> solution, explaining how it works so beginners can understand,
> describing you thought of it, and so on.
>
> I will give advance notice, at least:
> Eugene (77 char solution)
> Keith (74 char solution)
> BooK (your gs solution, you know the one)
> should definitely participate!
Thanks for the invitation, and thanks very much for running
another contest!
I see that several other people tried approaches using the ^
operator, but since mine was the shortest and probably the
weirdest, I'd better explain.
#!/usr/bin/perl -n
$==$.&1;$=^=7
..y*yuoeia***ord
for/./g;$=||print
Minus the obfuscation and golfish shortening, that's
#!/usr/bin/perl -n
$t = $. & 1;
$t ^= 7 . tr/aeiouy// * ord for /./g;
$t || print;
The -n means that each line of the input file is read and
assigned to $_. The next line sets a test variable to 0 if $.
(the line number) is even and 1 if it's odd. The next line
loops through all the letters in the line (the . in the regex
doesn't match the newline, because there's no /s modifier, and
/<whatever>/g in a list context returns all the matches). For
each letter, the result of tr/aeiou// (1 if it's a vowel, 0
otherwise) is multiplied by the ASCII value of the letter, and
then a 7 is appended to the front. The result of this strange
operation is xored with the test variable. So for each letter
in the word, one number is included in the xor: 797 for "a",
7101 for "e", 7105 for "i", 7111 for "o", 7117 for "u", 7121
for "y", and 70 for anything else. If you examine the bit
patterns of those numbers carefully (or run an exhaustive test
program), you'll find that there's no way to combine them with
xor so that they produce 1, and that the only way they can
produce 0 is if there's an even number of each (so that each
number cancels itself out). That means the test value will
never be 0 unless the line number is even and the word contains
even numbers of "a"s, "e"s, "i"s, "o"s, "u"s, "y"s, and
consonants. And an even number of consonants means an even
length for the word if the vowel restrictions are met. The
final line prints the word if the test variable is 0.
It took me a while to work out a calculation that would give
seven separate results (one for each vowel, and one for
everything else) that could not be xored together in such a way
that all the bits canceled out. I submitted a couple of
entries that passed the test program but that I realized later
weren't right. The first ones were this series:
#!/usr/bin/perl -ln
$%=0;$%^=ord for/[yuoeia]/g;$%||1&($.|y)))c)||print
#!/usr/bin/perl -ln
$%=$.&1;$%^=ord for/[yuoeia]/g;$%||1&y|||c||print
#!/usr/bin/perl -ln
$%=($.|y|||c)&1;$%^=ord for/[yuoeia]/g;$%||print
Unfortunately, simply taking the ASCII value of each vowel (in
these I was ignoring the consonants and checking the length
separately) didn't give a set of values with the right
property. The programs passed the test suite, but that was
only because the test suite didn't contain any words with odd
numbers of "e"s, "i"s, "u"s, and "y"s -- impudently unwieldy
words such as might be used fruitlessly by flunkeyish yuppies
(as I told Andrew). I withdrew the entry and substituted
something longer.
Later I came up with these:
#!/usr/bin/perl -ln
$%=($.|y|||c)&1;$%^=7+ord for/[yuoeia]/g;$%||print
#!/usr/bin/perl -n
$==$.&1;$=^=7+y*yuoeia***ord for/./g;$=||print
But adding 7 to the ASCII values of vowels and using 7 for
consonants wasn't the solution, either. I had neglected to
look at the effect of the initial $.&1 term. While it wasn't
possible for the values of the letters to cancel each other
out, they could combine to cancel out the initial 1 resulting
from an odd line number. If a word with odd numbers of "i"s
and "o"s, like "point", occurred on an odd line, it would
result in a 0 test variable and be printed erroneously.
I conducted a search for a digit and operator that would fit
the bill, and I found 7 (among other candidates) and the .
operator. Alas, the . did have to be preceded by whitespace to
avoid a syntax error, so I lost a stroke there.
Andrew's choice of this hole was just right. Challenging
enough to keep people away from their work and families until
the last moment, and with multiple promising approaches.
--
Keith C. Ivey <kcivey@cpcug.org>
Washington, DC
Thread Previous
|
Thread Next