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:
- Use @humn's
\let
approach to insert a \let
or \let\x
in front of the \R
to remove it silently.
- 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).
- 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.
\def \A #1{ \def \B ##1{a #1 from A an' a ##1 from B} }
$\endgroup$\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$