Wiki: TeX

Your best resource for TeX is the TeXBook, particularly chapter 20 ("Definitions (also called Macros)") and Appendix D ("Dirty Tricks"). Appendix B provides a list of almost all macros defined at startup.

The reference for plain TeX at tug.org is also a good resource.

TeX-autogolfer is a tool to help in golfing TeX. It's a combo of a simple minifier (remove whitespace, etc.) and a meta-macro system; for example you can write \usegolf{rebind\advance}, and it creates (effectively) \let\A\advance and replaces all of your uses of \advance with \A.

Basics

Differences from Plain TeX

The TeX language on the site is very similar to Knuth's plain TeX, with a few small modifications:

Looping over a string

The following code loops over all tokens until ;, replacing all - tokens with (DASH)

\def\f#1{\ifx#1;%
    \let\n\relax%
\else%
    \let\n\f%
    \ifx#1-(DASH)%
    \else #1%
    \fi%
\fi\n}

\f 0-185186-70-;

Improvement: an extra stop token

The following code loops over all tokens until ,;, replacing all - tokens with (DASH)

\def\f#1#2;{\ifx#1,\else
    \ifx#1-(DASH)%
    \else #1%
    \fi%
    \f#2;
\fi}

\f 0-185186-70-,;

Looping over two strings

The following code prints "Equal!" if two input token lists are equal.

\def\streq#1#2;#3#4;{
  \if#1,
    \if#3,
      % strings are equal, done
      Equal!
    \else
      % left string is shorter than right string
    \fi
  \else
    \if#3,
      % right string is shorter than left string
    \else
      %#1 and #3 are both not ','
      \if#1#3
        \streq#2;#4;
      \fi
    \fi
  \fi
}

\streq ABC,;DEF,; % (empty output)

\streq ABC,;ABC,; % outputs "Equal!"

Spaces

Space characters can be annoying to manage. Important spacing rules:

Math operations

Math can be performed in counters. Define a counter with \newcount, and print the value with \the.

\newcount\x
\x=15  % equivalent to the following line
\x15   % (the equals sign is optional)
\the\x % prints 15 as two tokens, "1" then "5"

Counters are 32-bit signed integers. Operations that overflow cause the program to instantly halt with no output.

\x\y            % x = y
\advance\x5     % x += 5
\advance\x by\y % equivalent to the following line
\advance\x\y    % x += y (the "by" text is optional)
\advance\x-\y   % x += -y
\multiply\x\y   % x *= y
\divide\x\y     % x /= y (floor divide)

There is no modulo operator. Modulo can be calculated (if you must) using the definition x % y = x - x / y * y, where x/y is floor division

% d = x - x % y, x = x % y (requires an extra counter)
\d\x\divide\d\y\multiply\d\y\advance\x-\d

Or modulo can be computed by repeated subtraction, assuming x and y are positive.

% x = x % y (slow)
\loop\ifnum\x>\y\advance\x-\y\repeat

ASCII conversions

Convert a char code to corresponding character with \char: \char97 gives the token a.

Convert a character to char code with a backtick: \number`a gives the two tokens 97, and \newcount\x\x=`a assigns 97 as the value of the counter \x.

Golfing

One-byte macro ending

If a macro you define takes an argument longer than one token, you might be tempted to use curly braces. However, \def can allow for a single end character, saving one byte per usage.

\def\f#1{something #1 something}
\f{123}\f{456}
% compare
\def\f#1;{something #1 something}
\f123;\f456;

\let

Commonly-used macros can be aliased with \let

\newcount\a\newcount\b\newcount\c
% compare
\let\N\newcount\N\a\N\b\N\c

At the top of a long solution, you might see a block of \lets like \let\N\newcount\let\I\ifnum\let\A\advance

Tilde is active

Tilde (~) is an active character (\catcode`\~=\active), so you can use it in lieu of one control sequences.

\let\N\newcount\N\a\N\b\N\c
% compare
\let~\newcount~\a~\b~\c

Form Feed

Form-feed (0x0c) is an active character (like tilde ~) defined as \par (\catcode`\^^L=\active \outer\def^^L{\par}). It is "outer," so you can only use it outside of constructs such as definitions and loops.

Form-feed can be typed in the editor by typing "0c" while holding down the Alt key.

1\par2\par3
% compare
1

2

3
% compare
1•2•3

Repeated macro vs loop

Repeating a macro several times is often shorter than a loop.

\newcount~\loop\ifnum10>~\the~,\advance~1\repeat
% compare (uses an extra variable)
\newcount\i\def~{\the\i\advance\i1,}~~~~~~~~~~

Newline inside loop

\newcount\i\loop\ifnum10>\i\the\i\endgraf\advance\i1\repeat
% compare
\newcount\i\def\f{\ifnum10>\i\the\i\advance\i1

\f\fi}\f

The recursive approach saves 3 bytes.