

   I liked the idea of a program that in a miscellaneous way challenges the
   user to type some of the legendary Perl phrases.

   The obfuscation in this program is mostly of a mathematical nature, and
   takes place within the innermost while loop. Most of the other bytes
   are spent in order to create content; the program embodies a game in which
   the user has to solve/answer three riddles/questons in order to enter
   "Sesame's cave". The questions are presented in a setting of rocks, magic,
   and the desert, but the answers should be familiar idiom for seasoned Perl
   hackers and trackers. Below some obfuscation and compression issues are
   itemized, followed by somewhat more lengthy explanation.

-  Storage of numbers as characters, reducing the size of the program.
   heavy usage of map(), split(), ord() and chr().

-  Matrix computation: ' "@I" ne "@J" ' idiom, map() function, and usage of
   hash function in order to implement heavily compressed matrix/vector
   product computation.

-  Matrix computation is carried out over the prime field GF 127 ("Galois
   field 127"). Characters are interpreted as numbers and vice versa.

-  printing of riddle/contours: hash controlled printing.
   scaling of iterands by sub i, which computes the inverse of any integer
   modulo 127.

-  Various shortcuts.

-  Major deficiency: sub i implements calculation of the inverse of an
   element in GF 127. As such, it is easily recognizible for mathematically
   experienced people. It really should have been implemenented as a combination
   of regexp matching and recursion. Alas, I am about to go on a leave, 
   so time is too short now, even after two years of waiting (see README).

-  Below, I give away the passwords. Maybe you found them already.
   If it is still a challenge to you, swap the two last 3-line fields
   of $M, .i.e.

$M = [ map { [map {c($_)} split "\n"] } split "\n\n",
' f(/! ej g+!D y_ e| y_m eDjIH y_ eJWKnguP]o k w~ o]E \\D` s oo ciw)r k"QaE
D$7 f dY,L _tE ^X*p `h qrb \\ qE ^S4 u x k~t4 t}j\\-3 qF lK1qN a][\'hN n [%:W
1e}} g p d c`F2F:aw d b,Vp ae2Yy u[7F [iC5 n{, ai/i^ h|p* n k>J,k7 v!v r

 g{+Y50{ h=c gyK=;Y4c=;9iucxY2 x m4 [ mqhnRj k"w7Md? x j \\ oBd}0 kU j_
f _ x pN&" s:Eh|74G j1 x:x mP oYz s _ \\e es c>Cd.jr Z mp%Nc0{ b ZQp a? \\} zr
:e^ei+D j# vL% i fXB wN&- p)ZIDe n.]_a4 vz v ntvq3 lp0 ta \\2 _.v i|X1 y \\

 ` s+8S+i_: y ]E+_1&F ]+g0_M&+_Y t b^1g \\F m dwR#RCT5np>#R bA nA[ k!h
W3PuG&" v ctY l ki>" l mk8x]lI k k2w lxzxrI a+#1*[tI^GA\\ v\\a?\\~1 j) u
wr k c4BX?F t]8% jrKA ` ah% j ^\'JB;0U) zh p nPw s-t/ \\]p h mEy x m)# lRCd a

1 r{ew y,{e[ i*{ ye2z|sbU x lHQ0uy9e16^_ o4 `2S p%P z ^ jjo i kCxOn `@i
2 y n$HI h n[ p Z ]^\'&?\\ j km o9 f<FKo)&oOcay `8?z:m q c!6a v7{z fHU v iyO
 z t{=l o [{1>{ fq8mHz+Up" t h asm5 dEXsme? rO w[( q# m1:j dL0 _C~nr z2 ^' ];

   The rewarding text takes now the place of the third riddle. There is a
   password for this text as well. Can you find it?



   The trick of the inner while loop is the way in which an answer to the
   questions is checked for validity. The check generates output, which, for
   incorrect answers prints a contour--picture in which the question fills the
   contours. In order to generate the question the first time, a wrong answer is
   raised by the program itself. The inner while loop implementens iterated
   matrix computation M on a vector @V of length $L. M has two special
   properties. There is a vector, call it FIX, which has the properties i) FIX is
   an *eigenvector* of M, and ii) the whole vector space eventually contracts to
   FIX (FIX is a fixed point, and it catches everything). The different matrices
   M are hardcoded within array @$M. The correct answer to the riddle, after
   being transformed into a vector of numbers, equals FIX. By checking the number
   of iterations, it can be verified whether the correct answer was given, for in
   that case only there will be just one iteration. If there is more than one
   iteration, certain a priori known properties of the iterands, which do not
   depend on the input, are used in order to generate the picture (see below),
   specifically, the contour of the rock Sesame.

   All arithmetic is carried out modulo the prime number 127. This makes it
   actually possible to implement the matrix multiplication M: with normal
   calculus, this matrix would have fractions in it, and computations would have
   to support arbitrary--length integers. Modulo a prime number (c.q. 127) all
   fractions, such has 23/7 have integer values: 23/7 == 94, because 
   94*7 % 127 == 23. Below, the program is discussed in greater detail.


   The riddles/questions are:

i)    who dares carve the rock in which Sesame lies concealed?
ii)   which magic map of sorts contracts the desert distances?
iii)  which heavenly creature covers the source of all magic?

      To which the answers are:

i)    just another perl hacker
ii)   the Schwartzian Transform
iii)  the Blue Camel

   The rewarding text if all riddles have been solved:

      Enter the cavernous realm of Sesame mighty scripter!

   The inner while loop is called while0, the successively enclosing while loops
   are called while1 and while2. Below, the working of the three while loops is
   explained. After that, a few other aspects are mentioned.

      while2:
   This while loops over the list of riddles, and sets the context (by
   means of $k which is the index for @$M) for each riddle. In @{$M->[$k]}
   three rows of numbers are stored, of which the first two represent part
   of the information needed to carry out the matrix multiplication M
   within while0. These two rows depend on the string which is the answer
   to the riddle. The third row represents a pointwise scaling of the
   fixed point FIX of M, such that the scaled vector @J prints the riddle
   in the contours of a rock.

   If all riddles have been presented, while2 checks to see if each riddle
   was solved. If so, control is manipulated so that the program exits
   after printing the contours of Sesame opened, plus a rewarding text
   within those contours. If not, the sequence of riddles is rewinded to
   its beginning.

      while1:
   Represents repeated guesses of the user to the same riddle. The
   guess/answer to the current riddle is stored in $_. Before the first
   iteration, $_ is set by while2 (to a wrong answer), in subsequent
   iterations, it is supplied by the user. $_ is transformed into a vector
   of numbers @V, which is the main iterand of while0. If the user
   supplies no \S character, c.q. just <RETURN>, while1 is exited.

      while0:
   Matrix multiplication M is carried out on @V. All arithmetic is done
   modulo 127, which is a prime number. Such arithmetic has very nice
   properties: each integer n has an *inverse* m modulo 127, e.g. the
   equation n*m==1%127 holds. Incidentally, this inverse is computed by
   sub i, using the property n**126==1%127 for each integer n. The
   mathematical setting is that of a *vector space* over the *field*
   GF(127). Without arithmetic modulo a prime number, it would be nearly
   impossible to work with matrix multiplication: support would be needed
   for full(-length) integer arithmetic over the rationals, such as
   supplied by Maple or Mathematica.

   What happens for arbitrary starting vectors @V, is that with every
   iteration, @V begins to look more like the fixed point FIX of M. The
   order in which this happens, is controlled both by the hash %P, and
   by information hardcoded in @{$M->[$k]}. For every iteration, one of the
   elements of @V becomes equal to the corresponding entry of FIX, until
   @V equals FIX. This is not the complete truth, since @V stabilizes at a
   *multiple* of FIX. This is, ahem, fixed by normalizing with the factor
   i($M[$a]). The routine i computes the inverse of any integer modulo 127. In
   order to enhance obfuscation, we do not compare @V and @W (which stores the
   previous value of @V), but @I and @J, which differ only from @V and @W by a
   pointwise scaling. Finally, this scaling is such that @J represents the
   current riddle (using the third row in $M->[$k]). In order to introduce the
   riddle, the program has to give a wrong answer once.

   Order starts to appear in @J in the same way as in @V. This order is
   precomputed in the hash %o. By checking the iteration index $i against
   the value under %o of the indices of the print, we decide which
   elements will be printed. This governs the  order in which columns
   appear in print.

   A correct answer is recognizable by the fact that it results
   immediately in a multiple of the fixed point FIX. There is a further
   subtle issue about the value of @I being saved from the last while0
   session, which is another benefit (or rather sine qua non) from doing
   while0 once before the user gets a say.

                           [++] There is a way to generate prematurely
                           aborted prints: by entering permuted
                           passwords such as 'just another hacker
                           perl' or just another perl hackre'.
   sub p

   pad and obfuscate password. requirements were that no vector entries are
   allowed to be zero (so that scaling is possible towards every vector)

   sub c
   
   used for decompressing vector of characters to vectors of
   numbers.

