[The four parts of this answer were originally posted separately, as indicated in the subject lines. Addendum 1 is the full text of Donald Arseneau's solution, which appeared in abridged form in part 3. Also addendum 2, containing a companion TeX encoder for my decoder, was not posted.] Date: 17 Aug 1994 16:24:12 -0400 (EDT) From: Michael Downes Subject: Around the Bend #11, solutions, part 1 of 4 To: info-tex@shsu.edu X-ListName: TeX-Related Network Discussion List Exercise 11 (several months ago) asked for an encoding scheme and minimal decoder that would permit setting up an Around the Bend post to include the answer in encoded form, decodable by simply running the posting through plain TeX. Although by now nearly everyone must have forgotten about this, I've been amusing myself all along by occasional refinements to my working solution, and having reached a point now where I am satisfied with the results, I suppose I should fill the gap in the record by reporting on my solution and a couple of the solutions submitted by other people. The design goals mentioned in the exercise were 1. Make the decoder as small as possible. 2. Make the encoding scheme `compact', ie strive to keep the encoded text not much larger than the unencoded version. 3. Allow ASCII 13,32--126 (at least) in the text to be encoded. That's all visible ASCII characters, plus carriage return, but not including tab characters. (In the expected kinds of text, tab characters can always be replaced by spaces or represented with TeX's ^^I or ^^09 notation.) My solution is demonstrated below. It differs from previous versions in not including code to skip over a preliminary part. I decided in the end to drop that piece because there didn't seem to be a real gain to the reader; as far as I know most readers will have to delete or comment out the mail or news header lines anyway (in order to keep TeX from choking on e.g. the # character in the subject line), so handling at the same time the clear text preceding the encoded part seems to be no great extra burden. (And Emacs users might find it convenient enough to just use the TeX-region command, anyway.) This is part 1 of 4; part 2 will contain some commentary on salient features of the problem; parts 3 and 4 will carry some good alternate solutions, submitted by Donald Arseneau and Peter Schmitt. Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ %%%% Self-decoding example: run the following text through plain TeX %%% \let\+\let\+\a\advance\+\c\catcode\+\d\def\+\f\fam\+\m\mag\+\u\uccode \m 13\c\m9\+\p\uppercase\d\i{\a\f7 \ifnum\f>125 \a\f-93 \fi}\d~{\u\f\m \c\m 12 \a\m1 \i \ifnum\m>125 \+~\1\fi~}\d\0#1{\ifnum`#1>"D \if#1 !\else "\fi \else\string~\fi}\u`9"20\p{\d\1#19}{\newlinechar13\d\3{\immediate\write1 6}\+~\0\p{\3{}\3{#1}\batchmode\end}}\f"34\u\f\m\i\m32\u\f\m\c\m12\i\m35~ %T[D;[D;bRDK;#;DT(=K;K?DK$;?!1=n/K[!M;wn;D[M!#KR=?;p[!?D$;`T[1T;[!1pR8?4 #pp;KT?;1T#=#1K?=D;[!;KT?;DR//(=K?8;D?K244Q[1T#?p;o(`!?D;PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP4wb8Sw#KT2#wD2(=M;e5!K?=!?Kl;Z {h55;UN++c\$cc++GNj);~;~BBIPW^elsz$+29@GNU\cj4qx")07>ELSZahov}'.5ELSZahov}'.5 Subject: Around the Bend #11, solutions, part 2 of 4 To: info-tex@shsu.edu X-ListName: TeX-Related Network Discussion List Discussion of Around the Bend #11; part 2. ENCODING The general form that I wanted the encoded text to have was: a solid block of characters, split into lines at the 72-character limit that is imposed on all Around the Bend postings. Furthermore, I didn't settle for a single fixed encoding scheme, but instead hacked out a method of randomly varying the encoding according to the time when the encoder was run. Thus each encoded posting gets a different cipher. Source character set: ASCII 13,32-126 Target character set: ASCII 33-126 Carriage return (13) cannot be included in the target set because of the 72-character limit on line length. If were included in the encoding, then the end of the current line in the encoded output would only occur at the next instance in the original text of the character that translates to 13. And depending on what that character is, who knows how long the encoded line could be? Perhaps as long as the entire text. Space (32) is not included in the target set for a subtler reason. If spaces in the encoded text happen to fall at the end of a line, they will be dropped by TeX during the decoding process, instead of decoded. So we either must exclude them from the target set, or make sure that they never fall at the end of a line. By excluding space from the target set, we make it possible for the decoder to use a space as its argument delimiter. If we have only one space, at the end of the encoded text, it is not so hard to ensure that it does not fall at the end of a line. But note that the decoder must make sure to change the catcode of space to something other than 10, so that it will not disappear if it falls at the *beginning* of a line. Note that the target set 33--126 is smaller than the source set 13,32--126. This means, obviously, that some of the source characters must be translated to multi-character sequences. Given that ~ can be assumed to be active in plain TeX, I arranged to translate a few characters into two-character sequences of the form ~X where potentially X is any character in the target set (including ~). Then the decoding process can translate back by giving ~ a suitable definition. If you did not use an active character as the prefix character in the two-character sequences, you might consider using TeX's ^^ notation to handle the extra characters in the source set. Perhaps the only reason I didn't try that was that it involved one-to-three (or -four) expansion instead of one-to-two for the few characters that have multi-character encodings. In a little more detail, here is how the encoding works: 1. Counter N is set to a random number in the range 33--126 (the target character set). Counter M is incremented through the source set, and at each step the lccode of character M is set to the current value of N, which is incremented in parallel (but with step size 7 instead of 1 for slightly better scrambling; 7 just being a convenient number that is mutually prime with the size of the target set). Then \lowercase{\immediate\write\outfile{...}} can be used to encode and write a line of characters to the output file. When counter N reaches 125, it is wrapped around to 33. Character 126 (~) is our active prefix character, so we don't want to make any single character translate to that via lccodes. 2. Special handling of a few characters is required at the boundaries of the source and target sets. Let I = the initial value of N. Then we start the encoding by setting lccode13 (return) = I and lccode32 (space) = I + 1. Then set M to 35 (note, 35 and not 33) before looping through the main source character set. 3. When M reaches 126, we have three characters left to define an encoding for: 126 ~, 33 !, 34 ". For simplicity, we continue to use counter N, but translate these three last characters to digraphs ~[N] ~[N+7] ~[N+14], where [N] means character N. DECODING Given the method of encoding described above, decoding is pretty simple. We just have to set up a suitable uccode table, and apply it. For a few characters we have to make a suitable definition for ~ so that ~x, ~y, ~z (where x y z are random) will be translated back to ~ ! ". Well, in fact this is not hard because by the way the encoding process was started up, we know that x y z will be translated to ^^M, space, and # by the uppercasing, so we merely have to define ~^^M to produce ~, ~space to produce !, and ~# to produce ". (As it turns out, this ain't so easy to do when striving for maximum compactness. My final version for this cost me no little work.) But given the proper setup, we finally execute a statement like \uppercase{\immediate\write16{...ENCODED TEXT...}}\end or actually, since the encoded text includes all characters in the range 33-126, but with a space character (32) at the end: \def\temp#1 {\uppercase{\immediate\write16{#1}}\end} \temp Clearly, this limits the amount of the encoded text to the currently available main memory of TeX. This is no real drawback for the limited application for which this decoder was written: encrypted answers to Around the Bend exercises. Donald Arseneau mentions in his solution (part 3, to follow) the idea of decoding line by line. This would not be too difficult, but would probably slightly increase the length of the decoder (maybe making it impossible for me to keep my own version of the decoder stuffed into the current five lines). Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456 789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ Date: 18 Aug 1994 15:37:41 -0400 (EDT) From: Michael Downes Subject: Around the Bend #11, solutions, part 3 of 4 To: info-tex@shsu.edu X-ListName: TeX-Related Network Discussion List Some selections from Donald Arseneau's solution and commentary. The entire solution is rather long so I won't post it in full; request it from Donald or me if you're interested. ======================================================================== Solution: \let~\let~\#\def\#\.{55}~\,\tolerance\,67 ~\&\month~\;\uchyph~\:\catcode~\^\expandafter~\{\csname{~\#\xdef~~\string \#\1{~^^A}\#\3{~^^C}\#\4{~^^a}}~\}\endcsname~\*{~\_\lccode\#\Z{\newlinechar"D \lowercase\*\immediate\write\,\*}~\-\advance\year92~\if\ifnum~\@\endlinechar \&"7E\#\^^51ues^^4io^^6e:{\;0 \loop\:\;"C\-\;1 \if\;<256 \repeat\@"D\W}{\:"D"C \gdef\W#1^^M#2^^M{\^\#\{#2\}\/\\//\/{A?^^M,Zz\over}\#\X##1^^M{\^\if^^8\{##1\^% \}\{#2\}\^\Y\else\^\X\fi}\X}}\#\Y{\;35\loop\_\,\;\if\;<\&\-\,\.\-\;1\if\,>\& \-\,-\year\fi\repeat\:1'0\:3"2\:33'7\_"20`"\_`""20\@-1\Z} \Question: *********************************************************************** *** Exercise 11 (hard): Write your own decoder to solve the problem I set for myself in Exercise 10: Using as few lines of TeX code as possible, set up an Around the Bend post containing a typical exercise so that it can be processed by plain TeX to (a) skip over the exercise text and (b) decode an embedded encoded answer. Come up with a better encoding idea than my previous one, that doesn't increase the size of the text by 300% during encoding. *********************************************************************** U"N5"M5[ZIm~f!!0dU!!0dU")"656"Yk3j"kH"jZ53"I"WZ5~m"I#kf"$Ej"WI34gj "XmI~~i"3Ij53H5m6x""]kEX!!0dU"$m46"Fk3j54#"FXkYFjm6"Ym"jk"3m46"5j"I 4iWIi"I46"I|k56"jZm"jmYFjIj5k4!!0dU"jk"3Fm46"YkXm"j5Ym"k4"5jx"")"lE 3j"Fk~53Zm6"5j"kHH"jk6Iix!!0dU!!0dU"KZIj")"WkE~6"~5Gm"jk"6k"53,!!0d U""A"YIGm"jZm"6m[k654#"YI[Xk3"3ZkXjmX"B4kjm"jZIj"54"Yi"HkXYIjf"I~~" jZm!!0dU""""YI[Xk[k6m"FXm[m6m3"jZm"}Em3j5k4f"WZ5[Z"~kkG3"WkX3m"jZI4 "ikEX"3k~Ej5k4xy!!0dU""A"93m"I[j5|m"[ZIXI[jmX3"XIjZmX"jZI4"J~kWmX[I [...] !!0d!!03!!03!!A{end!!A} ======================================================================== Commentary: % I did most of this a while ago, but wasn't really satisfied. Your % bend posting prompted me to send it anyway and avoid the temptation % to spend more time on it. I just polished it off today. % % What I would like to do is: % - make the decoding macros shorter (note that in my format, all the % macrocode precedes the question, which looks worse than your solution.) % - Use active characters rather than \lowercase to de-hash the answer, % and do separate \write for each line. That's to avoid memory overflow. % - likewise, chunk the \write s for the hashed text when running the hasher. ... %=================================================================== % This file should be clear! Only the hidden (hashed) text and % the macros to UNhash it should be obfuscated because they will % be given with the question. % % The hidden answer % ----------------- % % The printable characters # through ~ (35-126) are permuted % through a simple hashing with a chosen starting value and % multiplier. Non-printing characters are represented by their % hexadecimal codes in the form !!hh (where h is a hex digit % [higit?]); the ! character will act like ^ when the text is % decoded. I don't want spaces in the coded text, but I also % don't want to use !!20 because there are likely many spaces, so % space is represented by " and " is represented as !!20. There % are three other special (reserved) characters besides the % exclamation point: ^A, ^B, ^C (ascii 1,2,3). They are used as % follows: % % character use coded as % --------- --------------- ------------- % ! superscript \1 ( !!A1 ) % (for hex codes) % " space !!20 (trades with space) % ^A escape (\) \2 ( !!A2 ) % ^B opening ({) \3 ( !!A3 ) % ^C closing (}) \4 ( !!A4 ) % % % All other characters are represented by their permuted % printable character, or by their normal hexadecimal form: % !!15, !!0a, !!a4, !!7f etc. % % The original coding is done through active characters, with % all characters defined to produce their non-active coded text % (either hashed or hex). The decoding of hex (non-printing) % characters is automatic; the decoding of the special four is % done through simple definitions; the decoding of printable % characters is done by loading the de-hashed character values % into the \lccode and applying \lowercase. % % Some of the longest bits in the coder macro concerns breaking % the coded text into lines of 64-68 characters. If the first % character in a line (after breaking) is a period, or the first % two characters are --, the first character is given in hex % representation in fear of maniacal mail gateways. The other % dangerous characters like ^ ` \ ~ are not treated carefully % because they had to have been preserved for the macros to work % at all. % % The skipped question % -------------------- % % The question text is skipped with most special category codes % turned off. The only funtioning input is ^M due to \obeylines. % The active ^M checks each line of input looking for the marker % text to end the question material. The default marker is % %%----------Cut---Here---------- % The coded answer is assumed to immediately follow. % % % The coder % --------- % % [...] the coder routine [...] % asks for three file names: the \QuestionFileName should % contain the text of the question; the \SolutionFileName should % have the answer; The complete question/answer posting will be % written to \OutputFileName. (Run this file through plain TeX.) ... % There are 92 characters that will be hashed (35=# to 126=~). % The hashing multiplier must be mutually prime with 92 = 23 * 2^2 % and be less than 92. The start value (seed) can be anything % in the range 35-126. ... % All that's left to define are the skipper module and the decoder % module. They both are written into the posting to be execuded % by the receiver. They are compressed and obfuscated, but the % obfuscation is mostly just compression: using command symbols % like \, for longer command words, and using built-in registers % instead of allocating registers. Some of the abbreviations and % the choices of register are meant to be confusing and/or silly. % Plain-text versions of the modules are given here, as well as % a glossary of the obfuscation. % % Here is the skipper module. It is used in the form: % \Question: % a special line of text % anything that is skipped entirely, % until again seeing % a special line of text % % \def\Question:{\bgroup % \aftergroup\end % \allother % \Skipper} % % \Skipper starts the skipping by reading the delimiter text and % defining the macro `\SkipLine' to skip a line, testing for the % end text. The test is done by constructing a command name from % the sentinel text and from each line, and comparing them (with % \ifx). % % {\catcode`\^^M=12 % other % \gdef\Skipper#1^^M#2^^M{% read this line -> #1; next line -> #2 % % define sentinel macro: % \expandafter\def\csname#2\endcsname\/\\//\/{A?^^M,Zz\over}% % % define macro to read line and compare it with sentinel: % \def\SkipLine##1^^M{\expandafter% % \ifx\csname##1\expandafter\endcsname\csname#2\endcsname% % \expandafter \DecodeAnswer % finished skipping % \else% % \expandafter \SkipLine % keep skipping % \fi}% % } % % \DecodeAnswer unhashes the answer text and writes it to the % screen. The unprintable characters represented as !!hh are left % as they are (i.e., possibly unprintable!) Control-M (!!0d) will % break the text into lines on the screen; the linebreaks in the % hashed text are ignored. \HS is set to the seed value before % \DecodeAnswer is invoked. Date: 18 Aug 1994 15:38:30 -0400 (EDT) From: Michael Downes Subject: Around the Bend #11, solutions, part 4 of 4 To: info-tex@shsu.edu X-ListName: TeX-Related Network Discussion List Here is Peter Schmitt's solution to Around the Bend #11. \let~\catcode~` 13\let \let \u\uccode \b{ \e\expandafter \c\count{~` 14 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Michael: here is just another version for Exercise 11: - using comment space I have managed to pack the code into 1+3 lines of length 72. - accepting your proposal to omit from the argument delimiter the code fits into 1 + 3 1/2 lines. Maybe, that still a few characters can be saved, but I expect that a major gain can (if at all) only be achieved by a different coding method. best wishes, Peter P.S.: this is the second variant: \let~\catcode~12 9~`^13~13 9\let^\def{^^#1__{\egroup}~`\\9~`{9~`}9 ^ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% text to be skipped %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% __~` 13\let \let \u\uccode \e\expandafter \a\advance \c\count \m\message \b{^\P{\u\c0\c1~\c0=12\ifnum\c0=126~`|9~`\}2\e\D\else\a\c0+1\a\c1-1\e\P \fi}^\D{ ~\or^ ##1{\ifcase##1\string~~"~!~{~}{\newlinechar`!\m{!}}\m{~}% \e\end\fi}\uppercase\b\m\b}\c0`!\c1`}\P P.P.S.: I was lazy and have not prepared an updated version of the coded text. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } \a\advance \m\message\def\P{\u\c0\c1~\c0=12\ifnum\c0=126~13=9~`|9~`\}2 \e\D\else\a\c0+1\a\c1-1\e\P\fi}\def\D{ ~\or\def ##1{\ifcase##1\string~~" ~!~{~}{\newlinechar`!\m{!}}\m{~}\e\end\fi}\uppercase\b\m\b}\c0`!\c1=`}\P jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy j~~B;=| *;/:9>B@@Rml j~~#B:98B.,9.=,9+35.#B;=*;/:9>BBml~B;=*;/:9>B#ml~B;=*;/:9>B!ml j~| ~~~~~~~~~~~~~~~~~~~B;=*;/:9>B@ml~B+35.! j~~B;=*;/:9>B@@QmlB:98B+35.{m@@Q??#B97| ,/).!B.,9.=,9+35. jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| yyyyyyyyyy j+35..9:~*9&*~d~+35..507~5+~+*/..9:~<%~*'/~;/0+9;)*5(9~+)<+;,5.* j~| ~~~~~~~~~~~~~~;6=,=;*9,+~=*~*69~<97500507~/8~=~2509~d~?? j90;/:9:~*9&*~d~1)+*~| 90:~/0~/09~,576*~<,=;9~d~! jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| yyyyyyyyyyyyyyyyyyy jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| yyyyyyyyyyyyyyyyyy jyyy~*69~:9;/:507~1=;,/+ jyyy~*69~=;*)=2~1=;,/+~=,9~+2576*2| %~1/,9~;/1.25;=*9:~*/~=22/'~+6/,*9,~;/:9 jyyy~*69~*9&*~*/~90;/:9~1)+*~90:~/0~8| /,1899:~v]K[UU~mlu jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| yyyyyyyyyyyyyyyyy jB:98B.,9.=,9#B);;/:9~B;/)0*n~B;/)0*m j~~~~~~~~~~~~~B;=*;/:9| ~B;/)0*n~ml j~~~~~~~~~~~~~B580)1~B;/)0*n~a~mlh j~~~~~~~~~~~~~B;=*;/:9~>B@@Q~e j ~~~~~~~~~~~~~B;=*;/:9~>B"~e j~~~~~~~~~~~~~B;=*;/:9~>B!~l j~~~~~~~~~~~~~~~~~~~~| B9&.=0:=8*9,B:9;/:9 j~~~~~~~~~~~~~~B92+9~B=:(=0;9~B;/)0*~n~<%~~m j~~~~~~~~~~~~| ~~~~~~~~B=:(=0;9~B;/)0*~m~<%~qm j~~~~~~~~~~~~~~~~~~~~B9&.=0:=8*9,B.,9.=,9 j~~~| ~~~~~~~~~~~~B85! jB:98B:9;/:9#B;=*;/:9>B~B=;*5(9B)..9,;=+9B<7,/).B19++=79B<7,/| ).! jB;/)0*nakl jB;/)0*mamlh jB:98B02##B09'2509;6=,> lB19++=79# l!!B19++=79! j| B:98 n{m#B58;=+9B+*,507{mB+*,507 nB/, mB/, lB/,#B/,!B02#B/,!B9&.=0:=8*9,B90:B8| 5!y jB.,9.=,9 jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| yyyyyy jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| yyyyy jyyy~*69~90;/:507~1=;,/+ jyyyyyyyyyyyyyyyyyyyyyyy jB5119:5=*9B/.90/)*naB| 4/<0=19p;:: j~~~~~~~~~~~~B;=*;/:9> mB=;*5(9 j~~~~~~~~~~~~B;=*;/:9> lB=;*5(9 jB| :98B90;/:9~#B);;/:9>B n~a~B;/)0*n j~~~~~~~~~~~~~B);;/:9>B_~a~B;/)0*m j~~~~~~~~| ~~~~~B)..9,;=+9#B:98 n#B=::_m!B;=*;/:9>_B=;*5(9! j~~~~~~~~~~~~~B580)1~B;/)0*na| mli j~~~~~~~~~~~~~~~~~~~~B:98~ m#B=::#~1!l! j~~~~~~~~~~~~~~~~~~~~B:98~ l#B=::#| ~2!l! j~~~~~~~~~~~~~~~~~~~~B;=*;/:9>~B=;*5(9 j~~~~~~~~~~~~~~~~~~~~B;/)0*nan~B:| 98B2509#! j~~~~~~~~~~~~~~B92+9~B=:(=0;9B;/)0*n~<%~~m j~~~~~~~~~~~~~~~~~~~~B=:(| =0;9B;/)0*m~<%~qm j~~~~~~~~~~~~~~~~~~~~B9&.=0:=8*9,B90;/:9 j~~~~~~~~~~~~~~~~B8| 5 j~~~~~~~~~~~~~! jB:98B=::{m{l#B580)1~B;/)0*n~`~gf j~~~~~~~~~~~~~~~~~~~~B5119| :5=*9B',5*9n#B2509! j~~~~~~~~~~~~~~~~~~~~~B:98B2509#{m!~~~~~~B;/)0*na{l j~~~~~| ~~~~~~~~~B92+9~B9:98B2509#B2509{m!~B=:(=0;9B;/)0*n<%{l j~~~~~~~~~~~~~~~B85 j~~| ~~~~~~~~~~~B580)1~B;/)0*n~a~gf~B=::"m~B85 j~~~~~~~~~~~~! jB:98~~ n#B=::#~0!l! j B:98@@R#B=::#~5!lB5119:5=*9B',5*9n#B2509!B5119:5=*9B;2/+9/)*nB90:! j~~~~~~~~B;| =*;/:9>B@@QB=;*5(9~y jB:98@@Q#B=::#~4!l!~~~~~~~~~~~y jB;/)0*nakl~B;/)0*mamlh~B| 90;/:9 jyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| yyyyy j i This is trash: Text not displayed!} More Trash that is not displayed! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% [Addendum 1: Full text of Donald Arseneau's solution. To read the commentary you will need to run the text through TeX.] Date: 14 Oct 1993 01:52:26 -0800 (PST) From: Donald Arseneau Subject: Around the bends To: mjd@MATH.AMS.ORG \let~\let~\#\def\#\.{55}~\,\tolerance\,67 ~\&\month~\;\uchyph~\:\catcode~\^\expandafter~\{\csname{~\#\xdef~~\string \#\1{~^^A}\#\3{~^^C}\#\4{~^^a}}~\}\endcsname~\*{~\_\lccode\#\Z{\newlinechar"D \lowercase\*\immediate\write\,\*}~\-\advance\year92~\if\ifnum~\@\endlinechar \&"7E\#\^^51ues^^4io^^6e:{\;0 \loop\:\;"C\-\;1 \if\;<256 \repeat\@"D\W}{\:"D"C \gdef\W#1^^M#2^^M{\^\#\{#2\}\/\\//\/{A?^^M,Zz\over}\#\X##1^^M{\^\if^^8\{##1\^% \}\{#2\}\^\Y\else\^\X\fi}\X}}\#\Y{\;35\loop\_\,\;\if\;<\&\-\,\.\-\;1\if\,>\& \-\,-\year\fi\repeat\:1'0\:3"2\:33'7\_"20`"\_`""20\@-1\Z} \Question: *********************************************************************** *** Exercise 11 (hard): Write your own decoder to solve the problem I set for myself in Exercise 10: Using as few lines of TeX code as possible, set up an Around the Bend post containing a typical exercise so that it can be processed by plain TeX to (a) skip over the exercise text and (b) decode an embedded encoded answer. Come up with a better encoding idea than my previous one, that doesn't increase the size of the text by 300% during encoding. *********************************************************************** U"N5"M5[ZIm~f!!0dU!!0dU")"656"Yk3j"kH"jZ53"I"WZ5~m"I#kf"$Ej"WI34gj "XmI~~i"3Ij53H5m6x""]kEX!!0dU"$m46"Fk3j54#"FXkYFjm6"Ym"jk"3m46"5j"I 4iWIi"I46"I|k56"jZm"jmYFjIj5k4!!0dU"jk"3Fm46"YkXm"j5Ym"k4"5jx"")"lE 3j"Fk~53Zm6"5j"kHH"jk6Iix!!0dU!!0dU"KZIj")"WkE~6"~5Gm"jk"6k"53,!!0d U""A"YIGm"jZm"6m[k654#"YI[Xk3"3ZkXjmX"B4kjm"jZIj"54"Yi"HkXYIjf"I~~" jZm!!0dU""""YI[Xk[k6m"FXm[m6m3"jZm"}Em3j5k4f"WZ5[Z"~kkG3"WkX3m"jZI4 "ikEX"3k~Ej5k4xy!!0dU""A"93m"I[j5|m"[ZIXI[jmX3"XIjZmX"jZI4"J~kWmX[I 3m"jk"6mAZI3Z"jZm"I43WmXf!!0dU""""I46"6k"3mFIXIjm"JWX5jm"HkX"mI[Z"~ 54mx""^ZIjg3"jk"I|k56"YmYkXi"k|mXH~kWx!!0dU""A"~5GmW53mf"[ZE4G"jZm" JWX5jm"3"HkX"jZm"ZI3Zm6"jm2j"WZm4"XE4454#"jZm"ZI3ZmXx!!0dU!!0dU")"~ 5Gm"ikEX"YmjZk6"kH"[kE4j54#"jZm"3Fm[5I~"I[j5|m"[ZIXI[jmX"54"jZm!!0d U"}Em3j5k4"jm2j!!A4!!A4!!0dU""""AA"*k4I~6!!0dUuuuuuuuuuuuuuuuuuuuuu uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu!!0dU"^Z53"H5~m"3ZkE~ 6"$m"[~mIX!!A4""_4~i"jZm"Z566m4"BZI3Zm6y"jm2j"I46!!0dU"jZm"YI[Xk3"j k"9(ZI3Z"5j"3ZkE~6"$m"k$HE3[Ijm6"$m[IE3m"jZmi"W5~~!!0dU"$m"#5|m4"W5 jZ"jZm"}Em3j5k4x!!0dU!!0dU"^Zm"Z566m4"I43WmX!!0dU"AAAAAAAAAAAAAAAAA !!0dU!!0dU"^Zm"FX54jI$~m"[ZIXI[jmX3"C"jZXkE#Z"h"Bw-Ae@dy"IXm"FmXYEj m6!!0dU"jZXkE#Z"I"35YF~m"ZI3Z54#"W5jZ"I"[Zk3m4"3jIXj54#"|I~Em"I46 !!0dU"YE~j5F~5mXx"(k4AFX54j54#"[ZIXI[jmX3"IXm"XmFXm3m4jm6"$i"jZm5X!!0d U"Zm2I6m[5YI~"[k6m3"54"jZm"HkXY"!!A4!!A4ZZ"BWZmXm"Z"53"I"Zm2"65#5j !!0dU"oZ5#5j+%yc"jZm"!!A4"[ZIXI[jmX"W5~~"I[j"~5Gm"\"WZm4"jZm"jm2j"5 3!!0dU"6m[k6m6x"")"6k4gj"WI4j"3FI[m3"54"jZm"[k6m6"jm2jf"$Ej")"I~3k !!0dU"6k4gj"WI4j"jk"E3m"!!A4!!A4@."$m[IE3m"jZmXm"IXm"~5Gm~i"YI4i"3FI [m3f"3k!!0dU"3FI[m"53"XmFXm3m4jm6"$i"!!20"I46"!!20"53"XmFXm3m4jm6"I 3"!!A4!!A4@.x"^ZmXm!!0dU"IXm"jZXmm"kjZmX"3Fm[5I~"BXm3mX|m6y"[ZIXI[j mX3"$m356m3"jZm!!0dU"m2[~IYIj5k4"Fk54j,"\=f"\tf"\O"BI3[55"ef@fwyx"" ^Zmi"IXm"E3m6"I3!!0dU"Hk~~kW3,!!0dU!!0dU"""""[ZIXI[jmX""""""E3m"""" """""""""""[k6m6"I3!!0dU"""""AAAAAAAAA"""AAAAAAAAAAAAAAA""""AAAAAAA AAAAAA!!0dU"""""""""!!A4"""""""3EFmX3[X5Fj"""""""""Je""B"!!A4!!A4=e "y!!0dU"""""""""""""""""BHkX"Zm2"[k6m3y!!0dU"""""""""!!20"""""""3FI [m"""""""""""""""!!A4!!A4@."BjXI6m3"W5jZ"3FI[my!!0dU""""""""\=""""" ""m3[IFm"BJy""""""""""J@""B"!!A4!!A4=@"y!!0dU""""""""\t"""""""kFm45 4#"B{y"""""""""Jw""B"!!A4!!A4=w"y!!0dU""""""""\O"""""""[~k354#"B1y" """"""""JR""B"!!A4!!A4=R"y!!0dU!!0dU!!0dU"=~~"kjZmX"[ZIXI[jmX3"IXm" XmFXm3m4jm6"$i"jZm5X"FmXYEjm6!!0dU"FX54jI$~m"[ZIXI[jmXf"kX"$i"jZm5X "4kXYI~"Zm2I6m[5YI~"HkXY,!!0dU"!!A4!!A4e-f"!!A4!!A4.If"!!A4!!A4IRf" !!A4!!A4?H"mj[x!!0dU!!0dU"^Zm"kX5#54I~"[k654#"53"6k4m"jZXkE#Z"I[j5| m"[ZIXI[jmX3f"W5jZ!!0dU"I~~"[ZIXI[jmX3"6mH54m6"jk"FXk6E[m"jZm5X"4k4 AI[j5|m"[k6m6"jm2j!!0dU"Bm5jZmX"ZI3Zm6"kX"Zm2yx""^Zm"6m[k654#"kH"Zm 2"B4k4AFX54j54#y!!0dU"[ZIXI[jmX3"53"IEjkYIj5[c"jZm"6m[k654#"kH"jZm" 3Fm[5I~"HkEX"53!!0dU"6k4m"jZXkE#Z"35YF~m"6mH545j5k43c"jZm"6m[k654#" kH"FX54jI$~m!!0dU"[ZIXI[jmX3"53"6k4m"$i"~kI654#"jZm"6mAZI3Zm6"[ZIXI [jmX"|I~Em3!!0dU"54jk"jZm"J~[[k6m"I46"IFF~i54#"J~kWmX[I3mx!!0dU!!0d U"'kYm"kH"jZm"~k4#m3j"$5j3"54"jZm"[k6mX"YI[Xk"[k4[mX43"$XmIG54#!!0d U"jZm"[k6m6"jm2j"54jk"~54m3"kH"dRAdv"[ZIXI[jmX3x"")H"jZm"H5X3j!!0dU "[ZIXI[jmX"54"I"~54m"BIHjmX"$XmIG54#y"53"I"FmX5k6f"kX"jZm"H5X3j!!0d U"jWk"[ZIXI[jmX3"IXm"AAf"jZm"H5X3j"[ZIXI[jmX"53"#5|m4"54"Zm2!!0dU"X mFXm3m4jIj5k4"54"HmIX"kH"YI45I[I~"YI5~"#IjmWIi3x""^Zm"kjZmX!!0dU"6I 4#mXkE3"[ZIXI[jmX3"~5Gm"\"n"J"h"IXm"4kj"jXmIjm6"[IXmHE~~i!!0dU"$m[I E3m"jZmi"ZI6"jk"ZI|m"$mm4"FXm3mX|m6"HkX"jZm"YI[Xk3"jk"WkXG!!0dU"Ij" I~~x!!0dU!!0dU"^Zm"3G5FFm6"}Em3j5k4!!0dU"AAAAAAAAAAAAAAAAAAAA!!0dU !!0dU"^Zm"}Em3j5k4"jm2j"53"3G5FFm6"W5jZ"Yk3j"3Fm[5I~"[Ijm#kXi"[k6m3 !!0dU"jEX4m6"kHHx""^Zm"k4~i"HE4j5k454#"54FEj"53"\M"6Em"jk"Jk$mi~54m3 x!!0dU"^Zm"I[j5|m"\M"[Zm[G3"mI[Z"~54m"kH"54FEj"~kkG54#"HkX"jZm"YIXG mX!!0dU"jm2j"jk"m46"jZm"}Em3j5k4"YIjmX5I~x""^Zm"6mHIE~j"YIXGmX"53 !!0dU"UUAAAAAAAAAAOEjAAANmXmAAAAAAAAAA!!0dU"^Zm"[k6m6"I43WmX"53"I33EY m6"jk"5YYm65Ijm~i"Hk~~kWx!!0dU!!0dU!!0dU"^Zm"[k6mX!!0dU"AAAAAAAAA !!0dU!!0dU"NmXm"53"jZm"[k6mX"XkEj54mx"")j"53"3EFFk3m6"jk"$m"[~mIXx"") j!!0dU"I3G3"HkX"jZXmm"H5~m"4IYm3,""jZm"JqEm3j5k4<5~m(IYm"3ZkE~6!!0d U"[k4jI54"jZm"jm2j"kH"jZm"}Em3j5k4c""jZm"J'k~Ej5k4<5~m(IYm"3ZkE~6 !!0dU"ZI|m"jZm"I43WmXc""^Zm"[kYF~mjm"}Em3j5k4SI43WmX"Fk3j54#"W5~~"$m !!0dU"WX5jjm4"jk"J_EjFEj<5~m(IYmx""BLE4"jZ53"H5~m"jZXkE#Z"F~I54"^m&x y!!0d!!0dJ4mWXmI6Jq<5~m!!0dJ4mWXmI6J'<5~m!!0dJ4mWWX5jmJ_<5~m!!0d!!0d J4mW~54m[ZIXunT!!0dJYm33I#m{TKZIj"H5~m"[k4jI543"jZm"}Em3j5k4+1!!0d JXmI6ed"jk"JqEm3j5k4<5~m(IYm!!0dJkFm454Jq<5~muJqEm3j5k4<5~m(IYm!!0d !!0dJYm33I#m{KZIj"H5~m"[k4jI543"jZm"3k~Ej5k4+1!!0dJXmI6ed"jk"J'k~Ej 5k4<5~m(IYm!!0dJkFm454J'<5~muJ'k~Ej5k4<5~m(IYm!!0d!!0dJYm33I#m{KZIj "3ZkE~6"jZm"[kYF~mjm"Fk3j54#"$m"WX5jjm4"jk+1!!0dJXmI6ed"jk"J_EjFEj< 5~m(IYm!!0dJ5YYm65IjmJkFm4kEjJ_<5~muJ_EjFEj<5~m(IYm!!0d!!0dJ4mW5HJ5 H_;!!0d!!0dU"^ZmXm"IXm"Q@"[ZIXI[jmX3"jZIj"W5~~"$m"ZI3Zm6"Bw-uC"jk"e @duhyx!!0dU"^Zm"ZI3Z54#"YE~j5F~5mX"YE3j"$m"YEjEI~~i"FX5Ym"W5jZ"Q@"u "@w"T"@\@!!0dU"I46"$m"~m33"jZI4"Q@x""^Zm"3jIXj"|I~Em"B3mm6y"[I4"$m" I4ijZ54#!!0dU"54"jZm"XI4#m"w-Ae@dx!!0d!!0dJ4mW[kE4jJNM!!0dJ4mW[kE4j JjmYF!!0dJ[ZIX6mHJjkF["nJh"U"Z5#m3j"ZI3Zm6"[ZIXI[jmX"Be@dy!!0dJ[ZIX 6mHJ$kj["nJC"U"~kWm3j"ZI3Zm6"[ZIXI[jmX"Bw-y!!0dJ4mW[kE4jJXI4#m!!0dJ XI4#muJjkF["JI6|I4[mJXI4#mAJ$kj["JI6|I4[mJXI4#m"e"U"Q@!!0d!!0dJ6mHJ L{JXmI6ed"jk"JNI3ZME~j5F~5mX"JNMuJNI3ZME~j5F~5mXJXm~I2!!0d""J_;jXEm !!0d""J5H4EYJNMPJXI4#m"J_;HI~3mJH5!!0d""J5H4EYJNM">w"J_;HI~3mJH5!!0d ""JjmYFuJNM"J65|56mJjmYF"@w"JYE~j5F~iJjmYF"@w!!0d""J5H4EYJjmYFuJNM "J_;HI~3m"JH5"U"[Zm[G"[kYYk4"HI[jkX"kH"@w!!0d""JjmYFuJNM"J65|56mJjm YF"@"JYE~j5F~iJjmYF"@!!0d""J5H4EYJjmYFuJNM"J_;HI~3m"JH5"U"[Zm[G"[kY Yk4"HI[jkX"kH"@!!0d""J5H_;"Jm~3m"U"HI5~m6xxxXmFXkYFj!!0d"""""JYm33I #m{:~mI3m"m4jmX"I"4EY$mX"54"jZm"XI4#m"w"A"Q@!!0d""""""""jZIj"53"4kj "I"YE~j5F~m"kH"@"kX"@wx1JL!!0d""JH51!!0dJL!!0d!!0dJ4mW[kE4jJN'!!0dJ 6mHJL{JXmI6ed"jk"JNI3Z'mm6"JN'uJNI3Z'mm6JXm~I2!!0d""J_;jXEm!!0d""J5 H4EYJN'"PJjkF["J_;HI~3mJH5!!0d""J5H4EYJN'">J$kj["J_;HI~3mJH5!!0d""J 5H_;"Jm~3m"U"HI5~m6xxxXmFXkYFj!!0d"""JYm33I#m{:~mI3m"m4jmX"I"4EY$mX "54"jZm"XI4#m!!0d"""""""""J4EY$mXJ$kj[J3FI[m"A"J4EY$mXJjkF[x1JL!!0d ""JH51!!0dJL!!0d!!0dU"(kW"Wm"W5~~"XmI6"jZm"3mFIXIjkX"jm2j"jXmIj54#" 3Fm[5I~"[ZIXI[jmX3!!0dU"I3"kX654IXi"k4m3x""(mm6"jk"6k"jZm"[kYYI463" 54"YI[Xk3"3k"[Ij[k6m!!0dU"[ZI4#m3"6k4gj"ZEXj"jZm"[kYYI463")"WI4j"jk "6k!!A4!!0d!!0dJ$m#54#XkEF!!0d""Jm3[IFm[ZIXuAeJ26mHJ'mF!!0d""{J3jX5 4#JUJ3jX54#JUAAAAAAAAAAJ3jX54#JOEjAAAJ3jX54#JNmXmAAAAAAAAAA1!!0d""J 6mHJ6kCe{J[Ij[k6mnCeue@"1!!0d""J6mHJL{{J6k3Fm[5I~3Jm46~54m[ZIXuAe !!0d""JYm33I#m{^Zm"3mFIXIj5k4"jm2j"53,"nJ'mFgx"1U!!0d""JYm33I#m{a4jmX "I"XmF~I[mYm4j"kX"lE3j"FXm33"LmjEX4,"T1U!!0d""JXmI6Ae"jk"JjmYF!!0d" "J5H2JjmYFJmYFji"Jm~3m""J26mHJ'mF{JjmYF1JH511!!0d""JL!!0dJm46#XkEF !!0d!!0dU"B[Ijm#kX5m3"$I[G"jk"4kXYI~y!!0dU!!0dU"(kW"Wm"IXm"XmI6i"jk" XmI6"jZm"}Em3j5k4"I46"I43WmXf"I46"WX5jm"jZm!!0dU"kEjFEjx""'54[m"I~~ "jZ53"53"6k4m"W5jZ"I~~"[ZIXI[jmX3"$m54#!!0dU"nkjZmXgf"6mH54m"YI[Xk3 "jk"6k"I~~"jZm"FXk[m3354#"$mHkXm"[ZI4#54#!!0dU"I~~"jZm"[Ij[k6m3x!!0d !!0dJ4mW[kE4jJON!!0d!!0dU"(kjm,"^Z53"YI[Xk"W5~~"I~3k"$m"WX5jjm4"54 "3ZkXj"HkXY"W5jZ"jZm!!0dU"I43WmX"6m[k6mXx!!0d!!0dJ6mHJI~~kjZmX{JONu ."U"3mj"I~~"[Ij[k6m3"u"nkjZmXg!!0d"J~kkF!!0d"""J[Ij[k6mJONue@!!0dU" "J~[[k6mJONuJON""U"k4~i"E3m6"HkX"6m[k6mX!!0d"""JI6|I4[mJON"$i"e!!0d """J5H4EYJON>@-d!!0d"JXmFmIj!!0d"Jm46~54m[ZIXuew"U"\M!!0d1!!0d!!0dU "Km"W5~~"4mm6"jk"[kFi"~54m3"HXkY"jZm"}Em3j5k4"H5~m"I46"WX5jm"jZmY !!0dU"jk"jZm"kEjFEj"H5~m"|mX$Ij5Yx!!0d!!0dJ6mHJOkFiqEm3j5k4{Jm46~54m[ ZIXAe"J4mW~54m[ZIXAe"JOq1!!0d!!0dJ6mHJOq{U"U"jZ53"#5|m3"mXXkX"k4"4E ~~"54FEj"H5~mx"")j"3ZkE~6!!A4!!0d"JXmI6Jq<5~m"jkJ~54m"U"|mX$Ij5Y"3Z kE~6"$m"k4"Ij"jZm"YkYm4j!!A4!!0d"J5HmkHJq<5~m"J5YYm65IjmJ[~k3m54Jq< 5~m!!0d"Jm~3m"J5YYm65IjmJWX5jm"J_<5~m"{J~54m1Jm2FI46IHjmX"JOq!!0d"J H51!!0d!!0d!!0dU"^Z53"YI[Xk"YIGm3"I~~"[ZIXI[jmX3"I[j5|mf"I46"6mH54m 3"jZmY"I3"jZm5X!!0dU"Zm2"[k6m3,"!!A4!!A4ZZx!!0d!!0dJ6mHJ=~~=[jNm2{J 6mHJZm2ON{..1U!!0d""J~kkF!!0d""""J[Ij[k6m!!20JZm2ONuJI[j5|m!!0d"""" Jm6mHJZm2[Z{J~kWmX[I3m{Jm6mHJ4km2FI46JZm2[Z{JZm2ON111JZm2[Z!!0d"""" J(EYmX5[I~~iJm6mH{!!20JZm2ON1{!!A4!!A4JZm2[Z1U!!0d""""J5H4EY!!20JZm 2ON>!!20<JjkF[!!0d""""""JI6|I4[m"JjmYF"JNM"" U"I66"YE~j5F~5mX"jk"ZI3Z"|I~Emf""E354#xxx!!0d""""""J5H4EY"JjmYFPJjk F["JI6|I4[mJjmYFAJXI4#m"JH5"U"Yk6E~k"IX5jZYmj5[!!0d""""""JI6|I4[mJO N"e!!0d""JXmFmIj1!!0d!!0dU"(kWf"Wm"6mH54m"jZm"352"m2[mFj5k4"[ZIXI[j mX3!!0d!!0dJ6mHJa2[mFj{U!!0d""J(EYmX5[I~~iJ6mH{e1{!!A4!!A4=e1U!!0d" "J(EYmX5[I~~iJ6mH{@1{!!A4!!A4=@1U!!0d""J(EYmX5[I~~iJ6mH{w1{!!A4!!A4 =w1U!!0d""J(EYmX5[I~~iJ6mH{n!!A41{!!A4!!A4=R1U!!0d""J(EYmX5[I~~iJ6m H{nJ"1{!!201U!!0d""J(EYmX5[I~~iJ6mH{nJ!!201{!!A4!!A4@.1U!!0d1!!0d !!0d!!0dU"OkFi"jZm"3k~Ej5k4"HXkY"jZm"3k~Ej5k4"H5~mf"FmXHkXY"jZm"jXI43 HkXYIj5k43!!0dU"BE354#"Jm6mHyf"I46"WX5jm"kEj"54"IFFXk2x"dRA[ZIXI[jm X"~54m3x""^Zm"WZk~m!!0dU"3k~Ej5k4"YE3j"H5j"54"YmYkXi"$m[IE3m")"6k4g j"WI4j"jk"GmmF"[kE4j54#"jZm!!0dU"[ZIXI[jmX3"I46"kEjFEjj54#"jZmY"I"H mW"Ij"I"j5Ymx"")"6k4gj"3I|m"jZm"WZk~m!!0dU"Ym33"54"k4m"YI[Xk"jZkE#Z f"$m[IE3m"I6654#"jk"I"~k4#"~53j"#mj3"|mXi"3~kWx!!0d!!0dJ6mHJN56m'k~ Ej5k4{J6mHJ=~~{1JjmYFue"J4mW~54m[ZIXuew"Jm46~54m[ZIXew!!0d""J~mjJ !!A4JXm~I2"JN561!!0d!!0dJ6mHJN56{U"U!!0d"JXmI6J'<5~m"jkJ~54m!!0d"J5Hm kHJ'<5~m!!0d"""J5YYm65IjmJ[~k3m54J'<5~m"Jm2FI46IHjmX"JKX5jm'F~5j!!0d "Jm~3m!!0d"""Jm6mHJ=~~{J=~~"J!!A4{J4EY$mXJjmYF11U!!0d"""Jm2FI46IHj mXJm6mHJ[34IYm"rJ4EY$mXJjmYFJm46[34IYm{J~54m1U!!0d"""JI6|I4[mJjmYF" eJXm~I2!!0d"""Jm2FI46IHjmX"JN56!!0d"JH51!!0d!!0dU"^Zm"4m2j"YI[Xk3"I Xm"E3m6"jk"3F~5j"I"~53j"kH"[k6m"[ZIXI[jmX3!!0dU"54jk"I$kEj"dR"[ZIXI [jmX3,""jZm"H5X3j"hdR"54"I"YI[Xk"BCey"IXm!!0dU"WX5jjm4"jk"jZm"kEjFE j"H5~m"I46"jZm"XmYI546mX"IXm"~mHj"54"jZm!!0dU"YI[Xkx""^Zm"3F~5j"W5~ ~"4kj"54jmXXEFj"I4i"!!A4!!A4ZZ"3m}Em4[m3"BkX!!0dU"jZm"3Fm[5I~"!!A4 !!A4=w"3m}Em4[m3yx!!0d!!0dJ$m#54#XkEF!!0dJ[Ij[k6mewue@""U!!0dJ#6mHJ[ jX~Y{\\M1U!!0dJm46#XkEF!!0d!!0dJ6mHJKX5jm'F~5j{U!!0d""J6mHJ!!A4CCe{ J[34IYm"rCCeJm46[34IYm1U!!0d""Jm6mHJ=~~{J=~~""U"m2FI46"jk"XmI~"[ZIX I[jmX3!!0d""""!!A4!!A4.w!!A4!!A4.w!!A4!!A4=J3jX54#{m46!!A4!!A4=J3jX 54#11U"I66"jmXY54Ij5k4"[k6m3,!!0d""J6mHJx{1U""""""""""""""""""""""" """"U""11J[34IYm"m46Jm46[34IYm!!0d""J4mW~54m[ZIXuew"U"\M!!0d""Jm6mH J=~~{Jm2FI46IHjmXJK'J=~~"JxJxJxJxJxJxJxJxJxJxJm461!!0d""J5YYm65IjmJ WX5jmJ_<5~m{J=~~1U!!0d""J5YYm65IjmJ[~k3mkEjJ_<5~m!!0d1!!0d!!0dJ6mHJ K'{JfJfJfJfJfJfJfJfJOEjJXm~I21U"FI33"k|mX"v"T"v"u"dR"[ZIX!!0d!!0dJ6 mHJfCeJXm~I2"C@CwCRC-CdC?CvCQ{C@CwCRC-CdC?CvCQU"FI33"v"[ZIX!!0d""J5 H2CQJxJm2FI46IHjmXJm46m6mHJH5CeJXm~I21!!0d!!0dJ6mHJOEjJXm~I2CeC@Cw{ U")43mXj"~54mHmm6"[ZIXI[jmXf!!0d""J5H2Ce!!A4U"""""""""""U"$Ej"6k4gj "54jmXXEFj"I4i"!!A4!!A4ZZ!!0d""""J5H2C@!!A4J[jX~Y"CeC@CwJm~3m"CeC@C wJ[jX~Y"JH5!!0d""Jm~3m!!0d""""J5H2C@!!A4CeJ[jX~YC@CwJm~3m"CeC@J[jX~ YCwJH5!!0d""JH5"JK'1!!0d!!0dJ6mHJm46m6mHCeJm46{1U"m46"kH"jm2jf"3k"m 46"Jm6mH"I46"#k$$~m"XmYI5454#"lE4G!!0d!!0dU"=~~"jZIjg3"~mHj"jk"6mH5 4m"IXm"jZm"3G5FFmX"Yk6E~m"I46"jZm"6m[k6mX!!0dU"Yk6E~mx""^Zmi"$kjZ"I Xm"WX5jjm4"54jk"jZm"Fk3j54#"jk"$m"m2m[E6m6!!0dU"$i"jZm"Xm[m5|mXx""^ Zmi"IXm"[kYFXm33m6"I46"k$HE3[Ijm6f"$Ej"jZm!!0dU"k$HE3[Ij5k4"53"Yk3j ~i"lE3j"[kYFXm335k4,"E354#"[kYYI46"3iY$k~3!!0dU"~5Gm"Jf"HkX"~k4#mX" [kYYI46"WkX63f"I46"E354#"$E5~jA54"Xm#53jmX3!!0dU"543jmI6"kH"I~~k[Ij 54#"Xm#53jmX3x""'kYm"kH"jZm"I$$Xm|5Ij5k43"I46!!0dU"jZm"[Zk5[m3"kH"X m#53jmX"IXm"YmI4j"jk"$m"[k4HE354#"I46SkX"35~~ix!!0dU":~I54Ajm2j"|mX 35k43"kH"jZm"Yk6E~m3"IXm"#5|m4"ZmXmf"I3"Wm~~"I3!!0dU"I"#~k33IXi"kH" jZm"k$HE3[Ij5k4x!!0dU!!0dU"NmXm"53"jZm"3G5FFmX"Yk6E~mx"")j"53"E3m6" 54"jZm"HkXY,!!0dU"JqEm3j5k4,!!0dU"I"3Fm[5I~"~54m"kH"jm2j!!0dU"I4ijZ 54#"jZIj"53"3G5FFm6"m4j5Xm~if!!0dU"E4j5~"I#I54"3mm54#!!0dU"I"3Fm[5I ~"~54m"kH"jm2j!!0dU!!0dU"J6mHJqEm3j5k4,{J$#XkEF!!0dU"""JIHjmX#XkEFJ m46!!0dU"""JI~~kjZmX!!0dU"""J'G5FFmX1!!0dU!!0dU"J'G5FFmX"3jIXj3"jZm "3G5FF54#"$i"XmI654#"jZm"6m~5Y5jmX"jm2j"I46!!0dU"6mH5454#"jZm"YI[Xk "nJ'G5Fr54mg"jk"3G5F"I"~54mf"jm3j54#"HkX"jZm!!0dU"m46"jm2jx""^Zm"jm 3j"53"6k4m"$i"[k43jXE[j54#"I"[kYYI46"4IYm"HXkY!!0dU"jZm"3m4j54m~"jm 2j"I46"HXkY"mI[Z"~54mf"I46"[kYFIX54#"jZmY"BW5jZ!!0dU"J5H2yx!!0dU!!0d U"{J[Ij[k6mnJ\\Mue@"U"kjZmX!!0dU"J#6mHJ'G5FFmXCe\\MC@\\M{U"XmI6"jZ 53"~54m"AP"Cec"4m2j"~54m"AP"C@!!0dU"U""6mH54m"3m4j54m~"YI[Xk,!!0dU" ""Jm2FI46IHjmXJ6mHJ[34IYmC@Jm46[34IYmJSJJSSJS{=+\\Mf8DJk|mX1U!!0dU" U"6mH54m"YI[Xk"jk"XmI6"~54m"I46"[kYFIXm"5j"W5jZ"3m4j54m~,!!0dU"""J6 mHJ'G5Fr54mCCe\\M{Jm2FI46IHjmXU!!0dU"""""J5H2J[34IYmCCeJm2FI46IHjmX Jm46[34IYmJ[34IYmC@Jm46[34IYmU!!0dU"""""""Jm2FI46IHjmX"J*m[k6m=43Wm X"U"H5453Zm6"3G5FF54#!!0dU"""""Jm~3mU!!0dU"""""""Jm2FI46IHjmX"J'G5F r54m"U"GmmF"3G5FF54#!!0dU"""""JH51U!!0dU"1!!0dU!!0dU"J*m[k6m=43WmX" E4ZI3Zm3"jZm"I43WmX"jm2j"I46"WX5jm3"5j"jk"jZm!!0dU"3[Xmm4x"^Zm"E4FX 54jI$~m"[ZIXI[jmX3"XmFXm3m4jm6"I3"!!A4!!A4ZZ"IXm"~mHj!!0dU"I3"jZmi" IXm"B5xmxf"Fk335$~i"E4FX54jI$~m!!A4y"Ok4jXk~AM"B!!A4!!A4.6y"W5~~!!0d U"$XmIG"jZm"jm2j"54jk"~54m3"k4"jZm"3[Xmm4c"jZm"~54m$XmIG3"54"jZm !!0dU"ZI3Zm6"jm2j"IXm"5#4kXm6x""JN'"53"3mj"jk"jZm"3mm6"|I~Em"$mHkXm !!0dU"J*m[k6m=43WmX"53"54|kGm6x!!0dU!!0dU"J6mHJ*m[k6m=43WmX{U"B[kYFIX m"H5X3j"FIXj"W5jZ"J(kXYNI3Zy!!0dU"""JONuJ$kj["U"H5X3j"[ZIXI[jmX"BF~ I54"jm2jy!!0dU"""J~kkF"U"k|mX"ZI3Zm6"[ZIXI[jmX3!!0dU"""""J~[[k6mJN' uJON"U"YIF"[k654#"jk"F~I54"jm2j!!0dU"""""J5H4EYJON>JjkF[!!0dU"""""" "JI6|I4[m"JN'"JNM""U"I66"YE~j5F~5mX"jk"ZI3Z"|I~Emf""E354#xxx!!0dU"" """""JI6|I4[mJON"e"U"jZ53"ZmXm"FXm|m4j3"JN'"HXkY"$m54#"jm3jm6"FXmYI jEXm~i!!0dU"""""""J5H4EY"JN'PJjkF["JI6|I4[mJN'AJXI4#m"JH5"U"Yk6E~k" IX5jZYmj5[!!0dU"""JXmFmIj!!0dU"U"*mH54m"m2[mFj5k43x""OkYFIXm"jZ53"F IXj"W5jZ"Ja2[mFj!!0dU"""J[Ij[k6mnJ\\=u."U"nm3[IFmgf"J!!0dU"U"J[Ij[k 6mnJ\\tue"U"nkFm4gf"{"AA"E44m[m33IXi!!0dU"""J[Ij[k6mnJ\\Ou@"U"n[~k3 mgf"1!!0dU"""J[Ij[k6mnJ!!A4u?"""U"n3EFmX3[X5Fjgf"\"BHkX"Zm2"54FEjy !!0dU"""J~[[k6mnJ"unJ!!20!!0dU"""J~[[k6mnJ!!20unJ!!0dU"U!!0dU"""Jm46 ~54m[ZIXuAe"U"5#4kXm"~54m"$XmIG3"54"[k6m6"jm2j!!0dU"""J4mW~54m[ZIXu nJ\\M!!0dU"""J~kWmX[I3mJ$#XkEFJ5YYm65IjmJWX5jmJN'J$#XkEF!!0dU"1!!0d U!!0dU"s~k33IXi"kH"I$$Xm|5Ij5k43"I46"k$HE3[Ij5k43!!0dU"AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!!0dU!!0dU!!0dU"J~mj""""""""""""""""" h!!0dU"JN'"""BJjk~mXI4[my"""Jf"""""BJZI3Z"|I~Emy""""""""Ce!!0dU"JNM """"""""""""""""""Jx"""""BZI3Z"YE~j5F~5mXy""""C@!!0dU"JjkF["""BJYk4 jZy"""""J0"""""B~I3j"ZI3Zm6"[ZIX,"e@d"hy!!0dU"J$kj["""""""""""""""" w-"""""BH5X3j"ZI3Zm6"[ZIX,"w-"Cy!!0dU"JXI4#m"""""""""""""JimIX""""B JjkF[AJ$kj[/e,"Q@y!!0dU"JON"""""BJE[ZiFZy""""Jc"""""BI"[ZIXI[jmX"[k 6my!!0dU"J[Ij[k6m"""""""""""""J,!!0dU"J6mH"""""""""""""""""JC!!0dU" Jm2FI46IHjmX"""""""""J\!!0dU"J[34IYm""""""""""""""J{!!0dU"Jm46[34IY m"""""""""""J1!!0dU"J~[[k6m""""""""""""""J7!!0dU"JI6|I4[m"""""""""" """JA!!0dU"J$#XkEF""""""""""""""JT!!0dU"J5H4EY"""""""""""""""J5H!!0d U"Jm46~54m[ZIX"""""""""Jb!!0dU"J5H2"""""""""""""""J5H\\v!!0dU"J'G5 FFmX"""""""""""""JK!!0dU"J'G5Fr54m""""""""""""J&!!0dU"J*m[k6m=43WmX """"""""J]!!0dU"J~kWmX[I3mJ$#XkEFJ5YYm65IjmJWX5jmJN'J$#XkEF""""""J8 !!0dU!!0dU"^Zm3m"I335#4Ym4j3"IXm"WX5jjm4"jk"jZm"kEjFEj"$i"JKX5jm_Ej FEj"BI[jEI~~i!!0dU"$i"JK'9y"I46"jZm4"jZm"k$HE3[Ijm6"FXk[m3354#"[k6m "53"WX5jjm4"B#5|m4!!0dU"I3"I"FIXIYmjmX"54356m"B"y"IHjmX"JKX5jm_EjFE jyx"JKX5jm^ZmLm3j"53!!0dU"IEjkYIj5[I~~i"54|kGm6"jk"[kFi"jZm"}Em3j5k 4"I46"jZm4"jZm"I43WmXx!!0d!!0dJ6mHJKX5jm_EjFEjCeC@{J$m#54#XkEF!!0d" "J[Ij[k6mnJ\ue@"J4mW~54m[ZIXuew!!0d""Jm6mHJJ{J4km2FI46JK'9{Ce1{C@11 JJ1!!0d!!0dJ6mHJK'9CeC@{J~mjJJJ3jX54#"U"|mX$Ij5Y53Zf"I|k56"3FI[m3"I HjmX"[kYYI463!!0d""J5YYm65IjmJWX5jmJ_<5~m!!0d"""{JJJ~mjJJhJJJ~mjJJh JJJCJJJ6mHJJJCJJJx{C@1JJhJJJfJJJjk~mXI4[mJJJfCe1U!!0d""JI~~kjZmXJ[I j[k6mnBueJ[Ij[k6mnyu@!!0d""JIHjmXI335#4Ym4jJKX5jm^ZmLm3j!!0d""JjkG3 .u1!!0d!!0dJ6mHJKX5jm^ZmLm3j{J5YYm65IjmJWX5jmJ_<5~m{JjZmJjkG3.1!!0d ""J[Ij[k6mnBue@J[Ij[k6mnyue@!!0d""J5YYm65IjmJWX5jmJ_<5~m{J3jX54#JqE m3j5k4,1U!!0d""J5YYm65IjmJWX5jmJ_<5~m{J'mF1U!!0d""JOkFiqEm3j5k4!!0d ""J5YYm65IjmJWX5jmJ_<5~m{J'mF1U!!0d""{J=~~=[jNm2J(kXYNI3ZJa2[mFjJN5 6m'k~Ej5k41!!0d""Jm46#XkEF1!!0d!!0d!!0dJKX5jm_EjFEj{JjZmJN'1{JjZmJN MU!!0d1BhJ0JYk4jZhJcJE[ZiFZhJ,J[Ij[k6mhJ\Jm2FI46IHjmXhJ{J[34IYm{hJC J26mHhhJ3jX54#!!0dJCJe{h\\=1JCJw{h\\O1JCJR{h\\I11hJ1Jm46[34IYmhJT{h J7J~[[k6mJCJ8{J4mW~54m[ZIX!!20*!!0dJ~kWmX[I3mJTJ5YYm65IjmJWX5jmJfJT 1hJAJI6|I4[mJimIXQ@hJ5HJ5H4EYhJbJm46~54m[ZIX!!0dJ0!!20?aJCJ\\-eEm3\ \R5k\\dm,{Jc."J~kkFJ,Jc!!20OJAJce"J5HJc>@-d"JXmFmIjJb!!20*JK1{J,!!20 *!!20O!!0dJ#6mHJKCe\\MC@\\M{J\JCJ{C@J1JSJJSSJS{=+\\Mf8DJk|mX1JCJ&C Ce\\M{J\J5H\\vJ{CCeJ\U!!0dJ1J{C@J1J\J]Jm~3mJ\J&JH51J&11JCJ]{Jcw-J~k kFJ7JfJcJ5HJc>J0JAJfJxJAJceJ5HJfPJ0!!0dJAJfAJimIXJH5JXmFmIjJ,eg.J,w !!20@J,wwg?J7!!20@.n!!20J7n!!20!!20@.JbAeJ81!!0dy!!0d!!0dJm46!!0d !!0d!!03!!03!!A{end!!A} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% [Addendum 2: TeX encoder for my decoder. (mjd,18-Aug-1994)] % Source character set: 13,32-126 = 96 % % (Note exclusion of tab. Assumption: Text to be translated will % always be untabified first.) % % Target character set: 33-126. % % Carriage return (13) cannot be included in the target set because % of the constraint to have a maximum line length of 72 in the % encoded text. If 13 (carriage return) were included in the % encoding, then the end of the current line would only occur at % the next instance in the ciphered text of the character that % translates to 13. And depending on what that character is, who % knows how long the encoded line could be? Perhaps as long as the % entire text. % % Space (32) are not included in the target set for a subtler % reason. If spaces in the encoded text happen to fall at the end % of a line, they will be dropped by TeX during the decoding % process, instead of decoded. So we either must exclude them from % the target set, or make sure that they never fall at the end of a % line. % % By excluding space from the target set, we make it possible for % the decoder to use a space as its argument delimiter. If we have % only one space, at the end of the encoded text, it is not so hard % to ensure that it does not fall at the end of a line. But note % that the decoder must make sure to change the catcode of space to % something other than 10, so that it will not disappear if it % falls at the *beginning* of a line. \def\colon{:}\def\arrow{->}% \let\isx\message %\def\isx#1{} \iffalse % OK, here is how the encoding works. Start with \mag = random (in % the target range 33-125), first encoding value. Handle two % special cases first: ^^M encodes to \mag, space encodes to \mag % +1. Then start normal encoding at \fam = 35 (char 35 = ! encodes % to \mag +2, and so forth). When \mag reaches 126, we wrap it % around to 33 (don't want to encode any character to space). % Finally, when \fam reaches 126, we must handle the last three % characters (126,33,34: ~!") as digraphs: encode them as ~x~y~z, % where xyz are obtained by continuing to increment \mag. @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ ! "#$%&'()*+,-./0123456789:;<=>? R S~S~TTUVWXYZ[\]^_`abcdefghijklmnop @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} ~ qrstuvwxyz{|}!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ~R \fi % ^^^ \def\setup{% \def\notilde{}% later will be defined to include a tilde \def\encodeone{% \catcode\fam\active\lccode126\fam\lccode 48\mag \lowercase{\edef~{\notilde 0}% \isx{[\string~\colon \notilde 0\space\number\fam\arrow\number\mag]}% }% \advance\mag7 \ifnum\mag>125\advance\mag-93 \fi \advance\fam1 }% \def\do{\encodeone \csname do\ifnum\fam>125 stop\fi\endcsname }% % ASSUMPTION: \mag initialized before the call of \setup % Encode ^^M -> \mag \fam13 \encodeone % Encode space -> next \mag \fam32 \encodeone % Now encode the rest \fam35 \let\dostop\relax \do % Now \fam = 34, \mag = ?. We need to define encoding for % characters 34,33,126 ("!~) as ~z ~y ~x. But what are convenient % values for x y z? Why, just the next \mag's in sequence \edef\notilde{\string ~} \encodeone \fam33 \encodeone \encodeone } \def\outwrite{\immediate\write15{\outline}% % If a digraph occurred at the end of the line, carry over the % second character to the beginning of the next line. \expandafter\ifx\csname 73\endcsname\relax \else \expandafter\let\expandafter\1\csname 73\endcsname \expandafter\let\csname 73\endcsname\relax \charnum 1 \fi \checkeof} % For fast looking on screen: %\def\outwrite{\immediate\write16{\outline}\checkeof} \begingroup \let\0\catcode \0`\0 11 \0`\2 11 \0`\3 11 \0`\4 11 \0`\5 11 \0`\6 11 \0`\7 11 \0`\8 11 \0`\9 11 \0`\1 11 \gdef\outline{\1\2\3\4\5\6\7\8\9\10\11\12\13\14\15\16\17\18\19 \20\21\22\23\24\25\26\27\28\29\30\31\32\33\34\35\36\37\38\39 \40\41\42\43\44\45\46\47\48\49\50\51\52\53\54\55\56\57\58\59 \60\61\62\63\64\65\66\67\68\69\70\71\72} \endgroup \newcount\charnum \def\checkeof{\futurelet\next\encodemore} \def\tildecheck#1#2{\if \string~#1% \expandafter\def\csname\number\charnum\endcsname{#1}% \advance\charnum 1 \expandafter\def\csname\number\charnum\endcsname{#2}% \fi} \def\encodemore{\ifx\next\EOF \let\next\outwrite \let\checkeof\relax \global\tracingcommands2\global\tracingmacros2\global\tracingonline0 % At end of file, assume that there was a ^^M at the end, % translated to the digraph ~|. Remove it, to reduce the number of % blank lines that will be produced on screen during decoding. % BUT, if \charnum = 72, leave the ^^M there to avoid having the % space at the end of the line. \ifnum\charnum<72 \expandafter\def\csname\number\charnum\endcsname{ }% \else \def\1{ }% \fi \else \advance\charnum 1 \ifnum\charnum>72 \charnum 0 \let\next\outwrite \else \let\next\getnextchar \fi \fi \next} \def\getnextchar#1{% \edef\0{#1}% \expandafter\let\csname\number\charnum\endcsname\0\relax \expandafter\tildecheck\0\relax\relax \checkeof}% % For this we need just a unique no-op value for \ifx comparison. \def\EOF{\relax\relax} \def\writefile#1{\expandafter\checkeof\input#1 \EOF}% \begingroup % Define \0 to read in the text for \writepreamble. \def\0#1XXX#2^^JZZZ^^J{\endgroup \def\writepreamble##1{\begingroup % Convert ##1 into a hex number. \newlinechar=10 \chardef\0=##1\def\1####1"{"}% \immediate\write15{#1\expandafter\1\meaning\0#2}\endgroup}}% % Now change all special catcodes to 12. We don't use \dospecials % because we want to do backslash last, in conjunction with % \afterassignment. \catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\~=12 \catcode`\@=12 \catcode`\$=12 \catcode`\^=12 \catcode`\&=12 \catcode`\_=12 \catcode`\|=12 % The following line will turn off the last two remaining special % characters % and \, set end-of-line character to ^^J (for later % use in the \write), and then call \0. ^^M still has category 5 at % this point and the new value of \endlinechar won't get applied % until the *next* line is read, so the catcode assignment for \ % will get terminated properly by the space from ^^M, thus \0 will % get called before TeX attempts to read the % at the beginning of % the subsequent line. \catcode`\%=12 \endlinechar=10 \afterassignment\0 \catcode`\\=12 %%%% Self-decoding answer: run the following text through plain TeX %%%% \let\+\let\+\a\advance\+\c\catcode\+\d\def\+\f\fam\+\m\mag\+\u\uccode \m 13\c\m9\+\p\uppercase\d\i{\a\f7 \ifnum\f>125 \a\f-93 \fi}\d~{\u\f\m \c\m 12 \a\m1 \i \ifnum\m>125 \+~\1\fi~}\d\0#1{\ifnum`#1>"D \if#1 !\else "\fi \else\string~\fi}\u`9"20\p{\d\1#19}{\newlinechar13\d\3{\immediate\write1 6}\+~\0\p{\3{}\3{#1}\batchmode\end}}\fXXX\u\f\m\i\m32\u\f\m\c\m12\i\m35~ ZZZ \def\encodefile#1{% \immediate\openout15=encode.out \relax \begingroup % Get a random number from \time, normalize it to fall in the range % 33--125. First set \mag = \time mod 93, then add 33 to make it % fall in the proper range. \fam\time \mag\time \divide\fam93 \multiply\fam 93 \advance\mag-\fam \advance\mag 33 \message{======= Code shift: time \number\time\space --> mag \number\mag\space ============================}% \writepreamble{\number\mag}% % \setup uses \mag. \setup \charnum=0 \immediate\write16{Starting to create file encode.out . . .}% \writefile{#1}% \endgroup \immediate\closeout15 \relax \immediate\write16{The encoded output is in the file encode.out.}% } \immediate\write16{Enter the name of the file you want to encode:} {\catcode\endlinechar=9 \global\read-1 to\filnam} \encodefile{\filnam} \end