Eugene van der Pijll wrote:
>
> Among the entries, there were some that had something extra. They used a
> new, unique or surprising technique, used an unusual method, or were
> just ununderstandable. Some of these are:
>
> Kolakoski: Rick Klement (54.25)
> Mtv Europe (56.18)
> Rick Klement (57.20)
>
> I'd like to invite the authors of these solutions to explain these
> solutions to the public, or at least the original bits.
57.20 s/./$ARGV[1&pos]x$&/ge*/.{$ARGV[$_||=2]}/?print$&,$/:do$0
The infamous "[$_||=2]" perl bug. hehehe.
This started life (almost) as:
$_=2;s/./@ARGV[$|--]x$&/geuntil$|=/(.{$ARGV[2]})./;print$+,$/
then I found the pos trick, to:
$_=2;s/./@ARGV[1&pos]x$&/geuntil/(.{$ARGV[2]})./;print$+,$/
I wanted to pull the extra . in the pattern (because it
look messy, and I hoped to save those three strokes. That . is
really there to make sure the s/// runs at least once, because
otherwise /.{$ARGV[2]}/ would match and the s/// would not run.
To force s/// to run, I reshuffled to:
$_||=2until s/./@ARGV[1&pos]x$&/ge,/.{$ARGV[2]}/;print$&,$/
Since one of the tricks of golf is to remove duplicated elements, I
looked at the two '2's, and ask the natural question "can I get away
with only one '2'?"
Well, my natural impulse was to move the ||=2 inside the subscript,
which lead to:
s/./$ARGV[1&pos]x$&/geuntil/(.{$ARGV[$_||=2]})./;print$+,$/
Now I only used one '2', and it looked shorter, so I quickly ran it
through the test program to get a score, and it worked :)
Then I took a good stare at it: it couldn't work.
I'll get back to that.
I kept staring at that awkward /(.{$ARGV[2]})./ and wanted to get
to /.{$ARGV[2]}/ to save three strokes. The problem was that I started
with an initial value of '2', so I had to run the s/// once before
I could do the test, and the until tests first (do{}until would fix
that, but at too high a cost). That lead me to:
1until s/./@ARGV[1&pos]x$&/ge,/.{$ARGV[$_||=2]}/;print$&,$/
which won't work, because the initialization happens after the
first run of s///, so that lead to:
1until s/./@ARGV[1&pos]x$&/ge*/.{$ARGV[$_||=2]}/;print$&,$/
which does work, because the first s/// fails (empty string), while
the first // succeeds, so it goes around again, where the s/// will
succeed, but the // will fail until the sequence is long enough.
The * is there so that both must succeed before the print.
I kept looking at the $_||=2 as stuck at a value of 2 (perl bug - I said
it couldn't work).
Now the 1until ; is eight strokes where ?:do$0 is six, so I could
quickly shorten it to:
s/./$ARGV[1&pos]x$&/ge*/.{$ARGV[$_||=2]}/?print$&,$/:do$0
which is the 57.20 I submitted, and how I got to it.
The perl bug:
If you assume that [$_||=2] somehow sticks at 2, it's a perl bug,
and with that bug, the whole thing makes perfect sense.
Bugs are OK according to the rules: "however, it's perfectly fine
to abuse perl 5.6.1 bugs".
I figured that was what was happening here. It would have been
interesting to chase down exactly what the bug was, but there was
still a golf game in progress, and I had more golfing to do - there's
always more golfing to do until the game ends.
This solution quickly (16 hours later) got replaced by a shorter one
that did not have the $_||=2 in it, so I stopped thinking about it.
It turns out the whole situation can be interpreted as not a bug at all.
Adding some debug, it shows that the subscript in question really is
the Kolakoski number , and since that is a large number, usually refers
to an undefined element of the @ARGV array. Substituting an undefined
value into the regex gives /.{}/ and since (from perlre) the empty {}
is not a recognized quantifier, it is really interpreted as /.\{\}/,
which will not match.
also see: regcomp.c: "regcurly - a little FSA that accepts {\d+,?\d*}"
How does it stop?
It's expected behavior - hehehe. I refer you to:
http:[EMAIL PROTECTED]/msg00552.html
So eventually (really pretty quickly) the Kolakoski number overflows
and a subscript of -1 is used, which points to the correct count.
Lesson to be learned: try something before you say "that can't work" :)
--
Rick Klement