6
$\begingroup$

MathJax mirror on the wall, what is the fairest code of all?

Let’s find the minimal replacement for (replace this line) in the following MathJax code ...

$$\require{begingroup}\begingroup
(replace this line)
|Medusa|
\endgroup$$

... so that the rendered result is the reverse of $ \small |Medusa| $ :

$ \kern5em \small\texttt{ } |asudeM| $

The catch?    Any subsequent letters-only edits to the original Medusa should automatically be reflected in the result. Thus, the following ...

$ \kern5em \small\texttt { \$\$\require{begingroup}\begingroup } $
$ \kern5em \small\texttt { (replacement lines) } $
$ \kern5em \small\texttt { |MeDuSaEDITED| } \Large\raise-1mu\strut $
$ \kern5em \small\texttt{ \endgroup\$\$ } $

... would render as:

$ \kern5em \small\texttt{ } |DETIDEaSuDeM| $

Letters-only edits include the addition or deletion of any letters a through z, including uppercase, between the mirror’s | | edges. All letters might even be removed.

Spaces and line breaks are encouraged for readability, so they do not count in measuring the replacement code. Do not use an additional $ \small\texttt{\require{...}} $ or defeat the final call to $ \small\texttt{\endgroup} $. Admittedly, the audience for this puzzle is small. Please share any answer that even almost works.

In displaying formatted code in a spoiler, feel free to omit $$, which doesn’t seem to play well in that combination.

NOTE ☆ Before posting an answer, be sure to test it on a freshly loaded browser page ☆ Might also need to reload the page while editing, as inadvertent indiscretions in one edit can pervert MathJax results during later edits ☆

MathJax linx   (feel free to add)
Starring MathJax (puzzle)
MathJax exposed (puzzle)
Defining macros in MathJax
$\sf\scriptsize \raise2mu( L \raise4mu{\tiny A} \kern2mu \raise2mu) {\small T} \kern-1mu \raise-4mu E \kern2mu X$ commands in MathJax
$\sf\scriptsize {\small T} \kern-1mu \raise-4mu E \kern2mu X$ commands available in MathJax
MathJax reference at Mathematics Meta
MathJax questions at Meta SE | Physics Meta | Puzzling Meta | Mathematics Meta

$\endgroup$
6
  • 1
    $\begingroup$ Yes I'm starting to aim some mainstay coding puzzles at MathJax, but it is just too perfect for Puzzling to resist. Solutions are tested and proven right here under our very edits! And MathJax is a refreshing departure from Algol-derivative and stack-based languages, much as I enjoy those too, enhanced by user-friendly additions to La/TeX along with puzzle-nourishing variances from them/it. $\endgroup$
    – humn
    Commented Jul 15, 2016 at 6:24
  • 1
    $\begingroup$ Dammit: "MathJax internal buffersize exceeded; is there a recursive macro call?" - err yeah there is! $\endgroup$ Commented Jul 15, 2016 at 7:24
  • 2
    $\begingroup$ this works, @JonathanAllan (in other words no ref at hand): \def \A #1{ \def \B ##1{a #1 from A an' a ##1 from B} } $\endgroup$
    – humn
    Commented Jul 15, 2016 at 7:29
  • 3
    $\begingroup$ I can confirm that a solution is possible. Since the puzzle is only 7 hours old, I'm going to wait to post mine until others have had more of a chance to solve it on their own. $\endgroup$ Commented Jul 15, 2016 at 11:56
  • 1
    $\begingroup$ I should also confirm your conjecture that MathJax does not implement any conditional statements like \if or \ifx, etc., so you have to be a little more circumspect in managing a termination condition for a recursive process. It can be done, though. $\endgroup$ Commented Jul 15, 2016 at 13:36

2 Answers 2

3
$\begingroup$

Newest Solution

Based on @humn's comment, it seems that he has produced a single-\def solution of 34 characters that he has not yet posted. Because a definition requires at least 8 characters (four for the \def, two for the control sequence being defined, and two for the braces surrounding the replacement text), I was not surprised that one could save 7 by reducing the number of \def commands. But I was confused by how a single definition could be used recursively and still terminate itself at the right time. So I investigated how it could be done, and came up with my own version with 29 characters and only 1 definition, which I present below.

$$\require{begingroup}\begingroup \def\R#1#2|#3 {#3\R#2| %|% #1 } \R |Medusa| \endgroup$$

Since the one definition (which I will call \R) will be recursive, it will have to call itself, and be able to stop when the $Medusa$ string is fully reversed. The recursion that we have been employing so far has used two commands following the initial string: one for recursion and one for stopping. In order to go to only one \def, we could not operate this way, since this requires setting up the two commands before the recursion can start. With only one macro, we must start the recursion with only the initial string to work with, and nothing following it.

This means that the one macro must call itself, and yet somehow terminate itself as well. So it must include \R, and after the string is complete, it must prevent that \R from executing. I could think of three possible approaches to accomplish this:

  1. Use @humn's \let approach to insert a \let or \let\x in front of the \R to remove it silently.
  2. Move the \endgroup from the end to in front of \R so that it reverts to its original definition (but use something that has a default definition that does not produce output, like \let, rather than \R so that when it reverts it will do nothing).
  3. Insert % before the \R to comment it out.

Option 2 seemed impractical, especially as \endgroup is 9 characters, which is rather expensive, and getting ones hands on it at the correct time is tricky. Option 1 certainly can be made to work, but since \let is four characters while % is only one, I elected to use option 3.

The idea, then, would be to precede \R in the replacement string by one of its parameters, and that that parameter would be empty until the last character in the string to be reversed has been processed, then have it be a %. The question was, how would we get the needed % into a parameter without placing it after the string before the recursion starts (i.e., before the first call to \R)?

The key is that we know that \R will run at least once (even if the delimiters are empty, it must swap the delimiters). That means we can add something at the end of the $Medusa$ during the first call to \R that can be used to terminate the loop later. So the question becomes, how do we read an empty string as long as there are letters to be reversed, and a % when they are done?

Since we need to read an empty string on the first invocation of \R, we have to be able to do that using the initial data that we are given, namely |Medusa| followed by a line break followed by \endgroup. The only way to read an empty parameter (in the absence of {} in the input) is to use a delimiter following the parameter. There are two obvious choices: either use the empty string between the second | and the line break that follows, or use the empty string between the line break and the \endgroup.

The latter would require using \endgroup as the delimiter, which is too expensive, so the only real choice was to use the | followed by the line break. So the template for \R would have to be \def\R#1#2|#3 followed by a line break. This would give the character to move as #1, the remaining characters as #2, and the empty string as #3. Then the replacement text could start with #3\R#2| followed by a line break, so that the recursion would continue. The only thing remaining was to arrange for #3 to be % after the #2 becomes empty.

To figure out how to do that, we look at what happens when the string is complete. In that case, the input string will be \R| followed by a line break. So #1 will be the |, #2 will be everything up to the next |, and #3 will be everything from there up to the next line break. So to make this work, we need to add |% followed by a line break into the replacement string for \R so that on the last step, we will get #3 to be %. This will comment out the \R and anything else that follows it on that line (including #2 and the | in the replacement string), ending the loop.

So the definition should look something like

\def\R#1#2|#3
{#3\R#2|
|%
#1}

This will move letters to the end until there are no more letters, then will stop. But it also means each letter will have |% on the line before it, which will produce extra | in the output (one for each letter). We can eliminate that by preceding the | by a % to comment it out. Since the moved letter appears on a separate line, that doesn't interfere with it being output, but it does prevent anything else from being output.

So the complete code is as follows:

$‍$\require{begingroup}\begingroup
\def\R#1#2|#3
{#3\R#2|
%|%
#1
}
\R
|Medusa|
\endgroup$‍$

with 29 characters forming one recursive definition. Here is a live trace of the recursion in progress:

$$\require{begingroup}\begingroup \def\!#1%;{&(stop)&\break{#1}} \def\>#1#2 #3%;{\texttt{#1 #2}& \longrightarrow & \break{#3}#3%;} \def\break#1{\def\&{}\=.#1\endbreak\+ \endbreak\.} \def\=#1 #2\endbreak#3{#3#1 #2\endbreak#3} \def\+.#1 {\&\def\&{&&}\texttt{#1}\\\=.} \def\..#1\endbreak#2\.{\&\texttt{#1}\\} \def\R#1#2|#3 {\>\R[#1][#2][#3] #3\R#2| %|% #1 } \begin{array}{lcl} &&\break{\R |Medusa|}\\ \R |Medusa| %; \end{array} \endgroup$$

I believe that this is pretty much the minimal version of a recursive approach to this. With two definitions, each with one parameter and calling the other one, you would have 28 characters already, so to beat this, you can only use one definition (I don't see any way to do it with only the built-in macros). We have already seen that a macro with two parameters that calls itself uses 18 characters. This approach also requires a third parameter (4 more characters) plus a terminal %, and the initial call to \R, totaling 25 characters. So to beat this example you could use at most 3 more characters. In this example, those three are the three |, and the 29th character is the extra %, which seems the only possible redundant one.


Newer Solution

As noted in the comments, @humn came up with a new approach to terminating the loop by using % as the final command and inserting a line break in just the right place. At the last step, when the % is moved to the beginning of the loop, the line break that follows it means that the % acts as a comment character that comments out nothing, then the reversed text is emitted, and finally the % that was placed at the end for recycling acts as a comment character that comments out the rest of the input. The effect is to only output the reversed text, and stop the loop. This change means the final {}{} {} from my previous solution can be replaced by %, a savings of 5 characters, bringing this in at 41 characters and 2 definitions. I am hard pressed to see how any more characters can be removed.

Here is the code in action:

$$\require{begingroup}\begingroup \def\G#1 {\~#1 \~ %} \def\~#1#2 #3{#3 #2 #3#1} \G |Medusa| \endgroup$$

and the code itself:

$$\require{begingroup}\begingroup
\def\G#1
{\~#1 \~ %}
\def\~#1#2 #3{#3
#2 #3#1}
\G
|Medusa|
\endgroup$$

Finally, this is the self-tracing code:

$$\require{begingroup}\begingroup \def\>#1#2 #3#4#5.{\texttt{#1 #2}&\longrightarrow&\texttt{#3}\\&&\texttt{#5}\\[5px]#3#4#5.} \def\G#1 {\>\G[#1] \~#1 \~ %. } \def\~#1#2 #3{\>\~[#1][#2][#3] #3 #2 #3#1} \begin{array}{lcl} \G |Medusa| \end{array} \endgroup$$

In the last line of the trace, the first % is followed by a line break, while the last one is not, so the first comments out nothing, while the second comments out the following \~.


Previous Solution

Based on all the excellent work of @humn, I have a modified version of his 2-\def solution. It incorporates two ideas to reduce the number of characters: first, the definition of \G can be modified to use the line break as a delimiter rather than giving the | characters explicitly; this saves 3 characters. Second, we can use spaces as the delimiters for the buckets rather than |, saving 4 characters. The use of spaces for delimiters changes how the termination works (as explained below), and it turns out that {\let\ } is no longer needed (7 characters), but three empty parameters {} are needed (6 characters), for a 1-character savings. So the total savings are 8 characters, which brings this solution in at 46 characters and 2 \def statements.

$$\require{begingroup}\begingroup \def\G#1 {\~#1 \~ {}{} {}} \def\~#1#2 #3{#3#2 #3#1} \G |Medusa| \endgroup$$

$‍$\require{begingroup}\begingroup
\def\G#1
{\~#1 \~ {}{} {}}
\def\~#1#2 #3{#3#2 #3#1}
\G
|Medusa|
\endgroup$‍$

Note that the line break in the definition of \G is required (it is the delimiter for the #1, and so #1 will be |Medusa|, including the vertical lines). Here is the live trace of the code in operation, with "output" from the program shown between the lines indicating the macro substitutions (the $|asudeM|$ shows up between the last two substitutions).

$$\require{begingroup}\begingroup \def\>#1#2 #3\ {\\\texttt{#1 #2}&\longrightarrow&\texttt{#3}\\#3\ } \def\G#1 {\>\G[#1] \~#1 \~ {}{} {}\ } \def\~#1#2 #3{\>\~[#1][#2][#3] #3#2 #3#1} \begin{array}{lcl} \G |Medusa| \end{array} \endgroup$$

Here's how it works: as with @humn's solution, the reversed version of the text is stored after the \~ that is recycled for the recursive calls, but before the {} that is used to terminate the loop. How does that termination occur, here? The code takes advantage of the way that spaces are treated during parameter collection. For undelimited parameters, like the #1 in \~ that is followed immediately by #2, the next non-space character (or braced group of characters) is taken as the value of the parameter. Since we are using spaces as delimiters, when the original text is exhausted, the space delimiter will be the first thing following the \~, and it will be skipped when determining the #1 parameter, so #1 will become \~ (note that in the @humn solution, the | delimiter becomes #1 at this point.) That means that #2 is the reversed text (including the delimiters) and #3 is empty (due to the first {}), rather than the \let\ of @humn's solution. This is shown in the line of the trace just before the $|asudeM|$ shows up.

When the replacement text is formed, it starts with #3, which is empty (rather than the usual \~); that stops the loop. The #2 that follows inserts the reversed text, which is output at that point. This is followed by a space (which produces no output) and then by #3 (which is empty), and finally by #1, which is the \~. But because \G included {} {} at the end of its substitution string, this last copy of \~ ends up with all its parameters being empty, so it outputs nothing, and the execution is complete.

So a big difference here is that stopping the loop is accomplished by using an empty command. This differs from the @humn solution that uses \let cleverly to remove the looping macro (while at the same time cleaning up the trailing loop macro).

The last thing to note is that \~ is used here rather than \R. The reason for this is that when MathJax makes a parameter substitution that ends with a macro whose name consists of alphabetic characters, and the first character following the substitution is also alphabetic, it inserts a space so that the macro name is not misinterpreted (the following alphabetic characters would have been added to the name). This can be seen in the live trace for @humn's top solution, where the reversed text has spaces between each letter. Because we are using spaces as delimiters, we can't afford to have these spaces inserted by MathJax, so we change to a macro that has a non-alphabetic name; MathJax doesn't insert spaces for that case.

I hope that makes the operation of this solution clear.


Initial Solution

This is my original solution. It is 75 characters, if I counted correctly.

$$\require{begingroup}\begingroup \def\G#1|#2|{\R :#2|\R|\S} \def\R#1:#2#3|#4{#4 #2#1:#3|#4} \def\S#1:#2\S{#1|} \G |Medusa| \endgroup$$

$‍$\require{begingroup}\begingroup
\def\G#1|#2|{\R :#2|\R|\S}
\def\R#1:#2#3|#4{#4 #2#1:#3|#4}
\def\S#1:#2\S{#1|}
\G
|Medusa|
\endgroup$‍$

Here is the run history, with the parameters for the leading macro listed at the right.

\G |Medusa|             #1= #2=Medusa
\R :Medusa|\R|\S        #1= #2=M #3=edusa #4=\R
\R M:edusa|\R|\S        #1=M #2=e #3=dusa #4=\R
\R eM:dusa|\R|\S        #1=eM #2=d #3=usa #4=\R
\R deM:usa|\R|\S        #1=deM #2=u #3=sa #4=\R
\R udeM:sa|\R|\S        #1=udeM #2=s #3=a #4=\R
\R sudeM:a|\R|\S        #1=sudeM #2=a #3= #4=\R
\R asudeM:|\R|\S        #1=asudeM #2=| #3=\R #4=\S
\S |asudeM:\R|\S        #1=|asudeM #2=\R|\S
|asudeM|

I use \G to set up the recursion (just as Humn does). The \R macro is the heart of the matter, doing the recursive reversing, and \S is the "stop" macro, doing the cleanup and ending the process.

The original and reversed text are stored in two "buckets": the reversed text first, followed by a colon, followed by the original text, followed by a vertical line (|). The \R macro uses #1:#2 to read the current reversed text and the first character of the original text and moves the character to the beginning of the reversed text via #2#1: while inserting \R at the beginning again to continue the recursion.

The key is how to stop the recursion. This is done in \R by reading the next command to perform (as well as the text buckets). The #3| reads the rest of the unreversed text, and then #4 reads the command to perform. The replacement text #4 #2#1:#3|#4 puts the command first, then the reversed text so far, the colon, the rest of the unreversed text, the delimiter, and the next command (so the recursion continues).

To see why this works, you need to consider the situation when the unreversed text is empty. In this case, we have

\R asudeM:|\R|\S.

and so #1 is asudeM, and #2 is |, the next character, since that is the next character in the input. Then #3 is everything up to the next |, which is the \R, and #4 is the next token, \S. That is, we take advantage of the fact that #2 eats the unreversed-text delimiter when the unreversed text is empty, and so #3 eats the \R, and we end up reading \S as #4 rather than the usual \R. That stops the recursion. Then \S is left to clean up the buckets and output the final text.

Note that it would be possible for \S to isolate the reversed text and do what ever it wants with that, via \def\S|#1:#2.{...} so although we take advantage of the fact that the trailing delimiter is the same as the initial one, that need not be the case. That is, we could reverse [Medusa] as [asudeM] rather than ]asudeM[ if desired.

$\endgroup$
20
  • 1
    $\begingroup$ I suppose one could have \G redefine itself to be essentially \S and use \G in place of \S. But while that is two names, it is still really three macros. I haven't considered the other problem, but your macros do seem pretty concise for that. $\endgroup$ Commented Jul 16, 2016 at 13:03
  • 1
    $\begingroup$ MathJax does not include a tracing facility like this (though it is an interesting idea). I made my listing by hand. The error messages are turned off by default on SE, and so when I redid the editing code for them a few months ago, I made sure to re-endable them during editing. I'm glad you appreciate the change. $\endgroup$ Commented Jul 16, 2016 at 21:41
  • 1
    $\begingroup$ 46 characters = 8 fewer than what had seemed irreducible without cheating! This answer not only demonstrates ever more versatile use of delimiters but also once again improves the puzzle as a whole by sharing leaps in a solution process. $\endgroup$
    – humn
    Commented Jul 28, 2016 at 19:07
  • 1
    $\begingroup$ Click for an image of a comment with line breaks. It shows a slightly smaller version hiding inside your present solution. Not different enough for me to post legitimately, but similar enough that you could personalize it. $\endgroup$
    – humn
    Commented Jul 30, 2016 at 12:41
  • 1
    $\begingroup$ Was about to $\color{#0c0}{\large\raise-1mu\checkmark}$ this but thought of a way to get one $\small\texttt{\def}$ closer to a no-$\small\texttt{\def}$ solution. Luck got it to 34 chars, of which 3 still feel like surplus. Any lower and I won't be able to resist posting. Meanwhile, here's a likely-final preview of the dragon-like puzzle. Probably take longer for me to finish its presentation than for you to solve it. (Then back to $\small\texttt{\binary{}}$ and $\small\texttt{\stars{}}$, with ever more perspective and ever fewer tokens.) $\endgroup$
    – humn
    Commented Aug 8, 2016 at 22:52
4
$\begingroup$

Last solution

$$\require{begingroup}\begingroup \def \G |#1|{ | \R #1 |\R |{\let\ } } \def \R #1#2|#3{ #3 #2 |#3 #1 } \G |Medusa| \endgroup$$

This has 54 non-space replacement characters and exploits two economies:
•   $\small\texttt{\\}\color{violet}{\LARGE\raise-3mu\square}$ control space (backslash and space) is a control sequence but counts as only one character
•   By lurking behind the mirror until cleanup time, $~\small\texttt{\{\let\\}\color{violet}{\LARGE\raise-3mu\square}\texttt{\}}~$ acts like a macro without using $\small\texttt{\def}$

\require{begingroup}\begingroup
 \def \G     |#1|{   |   \R  #1  |\R  |{\let\ }   }
  \def \R #1#2|#3{       #3  #2  |#3  #1          }
   \G
|Medusa|
\endgroup

The live-tracing version below can be fun to play with in a temporary Ask Question window, where you can edit the $\small\texttt{|Medusa|}$ portion. Randomly adding letters or spaces elsewhere can also be amusing.  $\small\texttt{\\}\color{violet}{\LARGE\raise-3mu\square} \,$ is represented by$~\, \small\texttt{\_} \,$. One way to extract the self-tracing code (be sure to add $\small\texttt{\$\$}$ around it) is by right-clicking on the trace and selecting  $ \small \bbox[6px,border:1px solid black]{ \textsf {Show Math As} ~ \raise1mu\blacktriangleright }\kern-4mu\raise-5mu \bbox[6px,white,border:1px solid black]{ \textsf{TeX Commands} } $

$$\require{begingroup}\begingroup \def \d #1{ \kern1mu \raise-8mu { \scriptsize\texttt {#1} } \kern1mu } \def \t #1{ { \texttt {#1} } } \def \s #1{ { \small\texttt{#1} } } % \let \LET=\let \def \let #1#2#3\end{ \LET \let=\LET & \to~~~ | \LET#1#2#3\end } \def \G |#1|{ \t{\G|#1|} \kern 16mu & \to~~~ | ~ \rlap{ \s{\R #1|\R|{\let\_}} } \\ \R #1|\R|{\let\_} } \def \R #1#2|#3#4\end{ \t{\R}\d'\s{#1}\d'\s{#2}\d{|}\s{#3} & \to~~~ | ~ \rlap { \s{#3 #2|#3#1} } & \kern -1em \s{#4} \\ \kern-1em #3 #2|#3#1#4\end } \begin{array}{rlr} \G |Medusa| \end{array} \endgroup$$

.                    .-------------------------------.
.             .---- | ----------------------.         |
.            |      |                        |        |
.            V                               |.--.    |
.                  #1      #2          |    #3    |   |
.      |    \G   Medusa                       '--'    V
.      |    \R      M     edusa        |    \R          | {\let\_}    (reversal
.      |    \R      e     dusa         |    \R        M | {\let\_}     steps)
.      |    \R      d     usa          |    \R       eM | {\let\_}
.      |    \R      u     sa           |    \R      deM | {\let\_}
.      |    \R      s     a            |    \R     udeM | {\let\_}
.      |    \R      a     -            |    \R    sudeM | {\let\_}
.      .     .       . . . . . . . . .'         . . . . . . .'
.      .     .      '                          '                      (delimiter
.      .     .      '.------------------------ ' --------.             shift)
.                .- | ----------------------.  '          |
.               |   |                        | '          |
.               |                            | ' .---.    |
.      |    \R  |   |     \R asudeM    |   {\let\_}   |   |           (cleanup)
.               V                                     |   V
.                                                     |
.      |     \let\_       \R asudeM    |    \let\_    |   |
.                                              '-----'
.      |                     asudeM    |
.

Davide Cervone’s answer well explains how “buckets” can be used as variables and how macro calls can be stored in upcoming text to control recursion.

This solution has 5 conceivably non-essential characters, as the approach cannot avoid using the following 49 characters in some combination.

\def \G     |#1|{ | \R #1 | \R \let }
 \def \R #1#2|#3{ #1 #2 #3 #3 }
  \G

Non-space replacement characters can be whittled down to 50 by, what else, cheating, Invisibly at that, and in two ways. Can you tell how?

$$\require{begingroup}\begingroup \def \G #1 { \R #1@\ \R \ \let@ } \def \R #1#2\ #3{ #3 #2\ #3 #1 } \G |Medusa|   \endgroup$$

$$\require{begingroup}\begingroup
   \def \G   #1 {        \R   #1@\   \R   \ \let@   }
    \def \R  #1#2\ #3{   #3    #2\   #3   #1        }
     \G
|Medusa|  
\endgroup$$

One cheat is in the code above — remember, it is invisible — and the other is revealed by rendering an illegitimate trailing $\, \small\texttt{\\}\color{violet}{\LARGE\raise-3mu\square \,}$ control space, again represented by $\, \small\texttt{\_} ~$ in the diagram.

$$\require{begingroup}\begingroup \def \_ {\color{violet}{\LARGE\raise-3mu\square}} \def \G #1 { \R #1@\_ \R \_\let@ } \def \R #1#2\_#3{ #3 #2\_ #3 #1 } \G |Medusa|   \endgroup$$

.                        .----------------------------------.
.                 .---- | ----------------------.            |
.                |      |                        |           |
.                V                               |.--.       |
.                      #1      #2          \_   #3    |      |
.               \G  |Medusa|                      '--'       V
.               \R      |     Medusa|@     \_   \R              \_ \let@
.               \R      M     edusa|@      \_   \R            | \_ \let@
.               \R      e     dusa|@       \_   \R           M| \_ \let@
.               \R      d     usa|@        \_   \R          eM| \_ \let@
.               \R      u     sa|@         \_   \R         deM| \_ \let@
.               \R      s     a|@          \_   \R        udeM| \_ \let@
.               \R      a     |@           \_   \R       sudeM| \_ \let@
.               \R      |     @            \_   \R      asudeM| \_ \let@
.               \R      @     -            \_   \R     |asudeM| \_ \let@
.                .       . . . . . . . . .'        . . . . . . . . .'
.                .      '                         '
.                .      '.----------------------- ' --------.
.                    .- | ----------------------. '          |
.                   |   |                        |'          |
.                   |                            |' .--.     |
.               \R  |   \_   \R@|asudeM|   \_   \let    |    |    @
.                   V                                   |    V
.                                                       |
.                 \let       \R@|asudeM|   \_   \let    |    \_   @
.                                                   '--'
.                               |asudeM|   \_
.


Early non-solution to this puzzle, though a solution to a possibly better puzzle

Here’s an intermediate result previously offered as an example of how some things might work, juxtaposing the original $\small|Medusa|$ with its reverse, rendered first as a trace and then just the result.

$$\require{begingroup}\begingroup
   \def \go         |#1|{   \rep   |           #1 \stop   |        }
    \def \rep      #1#2|{         #1   \rep    #2         |   #1   }
     \def \stop  #1\stop{                                 |        }
      \go
|Medusa|
\endgroup$$

$$\require{begingroup}\begingroup \def \d #1{ \kern1mu \raise-8mu { \scriptsize\texttt {#1} } \kern1mu } \def \t #1{ { \texttt {#1} } } \def \s #1{ { \small\texttt{#1} } } % \def \go |#1|{ \t {\go|#1|} \kern 31mu ~~\to \kern-11mu & & \s{\rep |#1\stop|} \\ \rep |#1\stop| } \def \rep #1#2|#3\end{ \t {\rep}\d'\s{#1}\d'\s{#2} ~~\to \kern-11mu & \s{#1} \kern-9mu & \s{\rep#2|#1#3} \\ #1~~~ \rep#2|#1#3\end } \def \stop #1\stop#2\end{ \t{\stop}\d'\s{\rep|}\d{\stop} ~~\to \kern-11mu & & | #2 \end } \begin{array}{rrl} \go |Medusa| \end{array} \endgroup$$

$$\large =$$

$$\require{begingroup}\begingroup \def \go |#1|{ \rep | #1 \stop | } \def \rep #1#2|{ #1 \rep #2 | #1 } \def \stop #1\stop{ | } \go |Medusa| \endgroup$$

This is the result originally intended for this puzzle, because it displays the source and its reverse together, but got simplified ☆ at post time as I didn’t yet know what a solution might really involve. The code for this turned out to be simpler, though, than the code for the simpler-looking result, while still being tricky enough to be puzzle-worthy.

Mechanism: $ \small\texttt{\rep} $ leapfrogs letters by replicating until it lands after $ \small\texttt{\stop} $. Then $ \small\texttt{\stop} $ eats $ \small\texttt{\rep} $.

\go  |      M      e      d      u      s      a      |
\rep |      M      e      d      u      s      a      \stop      |
.    | \rep M      e      d      u      s      a      \stop      |             |
.    |      M \rep e      d      u      s      a      \stop      |            M|
.    |      M      e \rep d      u      s      a      \stop      |           eM|
.    |      M      e      d \rep u      s      a      \stop      |          deM|
.    |      M      e      d      u \rep s      a      \stop      |         udeM|
.    |      M      e      d      u      s \rep a      \stop      |        sudeM|
.    |      M      e      d      u      s      a \rep \stop      |       asudeM|
.    |      M      e      d      u      s      a      \stop \rep | \stop asudeM|
.    |      M      e      d      u      s      a                 |       asudeM|

Borrowing attributes from later solutions boils this down to 52 non-space replacement characters.

$$\require{begingroup}\begingroup \def \G |#1|{ \R | #1{\def\R{}} | } \def \R #1#2|{ #1 \R #2 | #1 } \G |Medusa| \endgroup$$

$$\require{begingroup}\begingroup
   \def \G    |#1|{   \R   |         #1{\def\R{}}   |        }
    \def \R  #1#2|{       #1   \R    #2             |   #1   }
     \G
|Medusa|
\endgroup$$


Initial solution

This  has  had 92 non-space replacement characters before Davide Cervone’s refinement improved it to 87 ( 84  79 if macro names were further abbreviated). This failed to recognize that $ \small\texttt{\@} $ could assume control at the right time without help from$ \,~\small\texttt{\[...]} $. Correcting that did, however, lead to the 54-character solution above.

$$\require{begingroup}\begingroup \def \go |#1|{ \rep | #1 \@ | } \def \rep #1#2|{ \[ #1 \@ \rep #2 | ] #1 } \def \[ #1\@#2]{ #2 } \def \@ #1\@{ | } \go |Medusa| \endgroup$$

$$\require{begingroup}\begingroup
   \def  \go       |#1|{   \rep   |                #1 \@   |            }
    \def  \rep    #1#2|{    \[   #1   \@   \rep    #2      |   ]   #1   }
     \def  \[   #1\@#2]{                           #2                   }
      \def  \@     #1\@{                                   |            }
       \go
|Medusa|
\endgroup$$

$$\require{begingroup}\begingroup \def \d #1{ \kern1mu \raise-8mu { \scriptsize\texttt {#1} } \kern1mu } \def \t #1{ { \texttt {#1} } } \def \s #1{ { \small\texttt{#1} } } \def \go |#1|{ \t{\go|#1|}\kern7mu \\ \rep |#1\@| } \def \rep #1#2|#3\end{ \t{\rep}\d'\s{#1}\d'\s{#2}\d| & \kern -9mu \s{#3} & \kern-1em \[ #1\@\rep#2|]#1#3\end } \def \[ #1\@#2]#3\end{ \t{\[}\d'\s{#1}\d{\@}\s{#2}\d] & \kern-9mu \s{#3} \\ #2#3\end } \def \@ #1\@{ \t{\@}\d'\s{#1}\d@ &\raise4mu\strut & | } \begin{array}{rlrl} \go |Medusa| \end{array} \endgroup$$

The mechanism borrows from the earlier non-solution above, but lands an additional role for $ \small\texttt {\@} \, $, previously named $ \small\texttt {\stop} \, $, giving it triple duty in macros: (1) Interior delimiter of the $ \small\texttt{ \[...\@...] } $ vanishing-act macro; (2) name and (3) terminal delimiter of the $ \small\texttt{ \@...\@ } $ macro that halts the $ \small\texttt{ \rep...| } $ loop by $ \small\texttt{ \@\rep...|\@ } $ swallowing it.

\go   |          M          e          d            |

 \rep |          M          e          d           \@           |
  \[  | \@  \rep M          e          d           \@           |  ]         |

            \rep M          e          d           \@           |            |
             \[  M \@  \rep e          d           \@           |  ]        M|

                       \rep e          d           \@           |           M|
                        \[  e \@  \rep d           \@           |  ]       eM|

                                  \rep d           \@           |          eM|
                                   \[  d \@  \rep  \@           |  ]      deM|

                                             \rep  \@           |         deM|
                                              \[   \@  \@ \rep  |  ]  \@  deM|

                                                       \@ \rep  |     \@  deM|
                                                                |         deM|
$\endgroup$
16
  • 1
    $\begingroup$ I have enjoyed watching your progress, here. I like the reuse of \R for the delimiters, though I did suspect that you could get away with | instead of one of them (but did't work out the details). I had considered using a braced expression for the stopping condition myself, but couldn't come up with one that I liked, so kudos for getting that to work. $\endgroup$ Commented Jul 17, 2016 at 21:55
  • 1
    $\begingroup$ The wrong data is still present in the listing (not the automatic one, but the hand-edited one). I see ` \G |Medusa| #1={\def\R...} #2=| #3= Medusa` where I expect to see ` \G |Medusa| #1=Medusa`. $\endgroup$ Commented Jul 18, 2016 at 11:04
  • 1
    $\begingroup$ Sorry to misunderstand earlier where the out-of-date #s were, @Davide Cervone, thanks once again! Good excuse to trot out the revised version of that approach, along with a sneak preview of an amusingly short solution, one in which $\small\texttt{\let}$ gets bounced around in a way that could only be discovered accidentally. $\endgroup$
    – humn
    Commented Jul 18, 2016 at 12:53
  • 1
    $\begingroup$ I have a few puzzle ideas of my own, if I can find time to post them. $\endgroup$ Commented Jul 18, 2016 at 14:02
  • 1
    $\begingroup$ Now reflected in the $\sf\small|MathJax~mirror|$, a very invalid solution that looks legitimate and behaves perfectly. Saves 4 characters by getting away with using no |s (illegitimately). You might be amused, @Davide C. $\endgroup$
    – humn
    Commented Jul 20, 2016 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.