What tips do people have for golfing in TeX/LaTeX? Please post one tip per answer, each at least somewhat specific to TeX/LaTeX.

Context: I noticed this answer and that there is no tips question for TeX/LaTeX, so I'm creating this one. There's some overlap with the narrower question tips for golfing in TikZ (as TikZ is a specific macro package on top of TeX/LaTeX): answers to this question will probably also apply there, but not the other way around.

  • \$\begingroup\$ How can you golf a non-programming language? \$\endgroup\$ – user64742 Jun 2 '17 at 14:51
  • 1
    \$\begingroup\$ @TheGreatDuck Very poorly :-) \$\endgroup\$ – ShreevatsaR Jun 2 '17 at 14:53
  • \$\begingroup\$ @TheGreatDuck Actually, TeX is a programming language, even if usually it's used only as a typographical one. \$\endgroup\$ – gvgramazio May 15 '18 at 22:22

14 Answers 14


Consider internal LaTeX macros rather than the documented ones

For example, \roman is a documented LaTeX macro that works on LaTeX counters. To turn 42 into XLIV you'd have to use something like


Instead, by looking up how \roman is implemented (use \show\roman to get this interactively, instead of reading the source files), one can see that it's implemented in terms of a useful macro called \@roman, and instead use that directly:


\catcode`@11 is the golfy way of writing \makeatletter (clean way in LaTeX) or \catcode`\@=11 (clean way in plain TeX). It's needed only once at the beginning, after this you can use macro names containing @.


~ can be used as a macro (as can other active characters)



\def\a{...some definition...} ... use \a...


\def~{...some definition...} ... use ~...

Explanation: Generally macros in TeX are “control sequences”: you can define \something or \a. But you can go even shorter, by using an active character. The only active character that is present by default (in plain TeX / LaTeX) is ~ (used for “ties”, i.e. defined as \penalty \@M \ in plain TeX (a penalty of 10000 followed by a space), and as \nobreakspace {} in LaTeX). But nothing stops you from redefining it for whatever purpose you need.

Further: you can do the same with any other character by setting its catcode to \active (13). For example, making Z an active character has a "cost" of 12 bytes: \catcode`Z13. Then you can use simply Z everywhere instead of a macro like \z. For some characters that start out with a special meaning, the direct backtick approach doesn't work and you need one more character: \catcode`\Z13 or \catcode90=13.


\def can match fixed patterns

Let's say you had \def\a #1 #2 {...some definition here...}. Then when you call it on a string like \a Act42, Scene26, inside the macro the arguments may be assigned like #1 <- Act42,, #2 <- Scene26 and then you'd have to do some further work to extract out the relevant parts. Instead, one could directly write

\def\a Act#1, Scene#2 {...some definition here...}

and then calling it as \a Act42, Scene26 would directly set #1 <- 42 and #2 <- 26.

(This is basically the definition of \def, but it's easy to forget as one doesn't typically do this in LaTeX, preferring to pass arguments into {} as if they were function calls.)


Choosing between plain TeX and LaTeX

A lot can be said about this, but in short, compare a typical plain TeX document that prints "Hello" with a typical LaTeX document for the same:




The "cost" of LaTeX (wrt code golf) is obvious; the "benefit" of course is that LaTeX comes with a library of many pre-written macros and packages, some of which may be useful for the task at hand.

  • \$\begingroup\$ I was stuck into using LaTeX because of \@Roman (getting the uppercase to work in plain would cost a lot of bytes) -- but plain TeX would often be shorter. \$\endgroup\$ – Chris H Jun 1 '17 at 13:28

\input ... is shorter than \usepackage{...}

For example, you can write

\input color

instead of


which is 6 less bytes.

  • 9
    \$\begingroup\$ It is useful to point out however that \usepackage becomes more efficient as the number of packages you include goes up. Since you can use more than one package with only one \usepackage statement, but require an \input for every package, If you are using 3 or more packages, \usepackage becomes the better option. \$\endgroup\$ – Wheat Wizard Jun 2 '17 at 11:43

If using LaTeX, use a short documentclass (idea by Chris H)

Instead of starting with the typical


one can choose shorter document classes like book or even



  • \$\begingroup\$ You should remember to stay within the specs of the question, article by default numbers its pages, this can be considered extra output. Perhaps a meta question is in order to determine what document classes should be allowed. \$\endgroup\$ – Wheat Wizard Jun 1 '17 at 5:48
  • \$\begingroup\$ @WheatWizard Good point. I think it may be up to the individual question whether page numbers are considered extra output. \$\endgroup\$ – ShreevatsaR Jun 1 '17 at 5:50
  • \$\begingroup\$ I reckon a minimal class would be a good idea - a single letter name and no page numbering \$\endgroup\$ – Chris H Jun 1 '17 at 13:26
  • \$\begingroup\$ I've put together a g.cls which is just article.cls with \pagenumbering{gobble} but as github is down I can't put it up for now \$\endgroup\$ – Chris H Jun 1 '17 at 13:51
  • \$\begingroup\$ g.cls \$\endgroup\$ – Chris H Jun 2 '17 at 13:31

Creating an environment called myenvironment generates the commands \myenvironment and \endmyenvironment. These are used internally to begin and end the environment. In some cases they can be used as shortcuts. For example, instead of

\item abc

one can do

\item abc

Not supported, not reliable, doesn't work in all cases, use at your own peril, etc. etc.

  • 3
    \$\begingroup\$ You can often do \itemize{...} for even more savings. \$\endgroup\$ – Wheat Wizard Jun 1 '17 at 19:50

\usepackage{packagea,packageb,packagec} works, so long as you're not passing options to the packages.


Run lines together. Line breaks are rarely needed in LaTeX/TeX, as compared to many long-form languages.


Use local { ... } groups wisely

As pointed out in this answer, active characters like ~ can be used as a macro name. Unfortunately, ~ is the only active character by default, and changing the catcode for another character is expensive: \catcode`!13 takes 12 bytes. If the new macro definition is only needed in a small region of your code, local groups can be a solution.

When TeX enters a new local group opened by {, it creates a new grouping level on the internal save stack. This means that all current macros and registers are saved. Any modifications to them (unless explicitly marked as \global) are now only being active until the group is closed by }. This means that ~ can be redefined within a group, used there with the new definition, and the old defintion will automatically be restored after the group has finished.

Here's an example:

~ -- {\def~{123}~} -- ~

This outputs

abc - 123 - abc

An interesting side effect of this grouping mechanism is that the old values are still available inside the group until they are changed there. To illustrate that, imagine we want to print a number of characters based on the value of a counter, pad them with spaces up to a fixed length, and go on with the original counter value. This could be achieved by the following:

Print a char \the\x\ times,
{\x=-\x \advance\x 10 pad with \the\x\ spaces,}
and go on with x=\the\x.

which outputs

Print a char 3 times, pad with 7 spaces, and go on with x=3.

This grouping behaviour is especially important if you want to use TeX's standard macros for looping \loop ... \repeat nested. These macros define internal commands and use them for determining how to proceed. Nesting them without putting the inner loop into braces will confuse the internal commands and lead to unexpected behaviour.


Some macros that you might expect to need braces round their arguments actually don't, especially when used inside another macro with #1-style arguments.

Most macros only need braces if there's more than one token (character or control sequence) in the argument.

\mymacro1          % equivalent to \mymacro{1}
\mymacro{12}       % equivalent to \mymacro{12}
\mymacro a         % equivalent to \mymacro{a}
\mymacro{ab}       % equivalent to \mymacro{ab}
\mymacro\foo       % equivalent to \mymacro{\foo}
\mymacro{\foo x}   % equivalent to \mymacro{\foo x}

If you need to use the same macro with a long name several times, you can use \let to define a shorter alias.


This saves two bytes on \def\a{\mymacrowithalongname}, if you don't need multiple tokens in the definition.

Instead of a macro name, you can have an active character to save on backslashes.

Note that \let doesn't only work with macro names but also with built-in primitives. For example, if you use a lot of \ifnum ... \fi constructs in your code, defining \let\i\ifnum and instead using \i ... \fi could save you a few bytes. This even works for \let itself: \let\l\let.


The advancement of counters, such as

\advance\u by 1
\multiply\u by 3
\divide\u by 2

also work as

\advance\u1        % \u = \u + 1
\advance\u-1       % \u = \u - 1
\multiply\u3       % \u = \u * 3
\multiply\u\u      % \u = \u * \u
\divide\u2         % \u = \u / 2

The same principle also works for initialisation:


sets the counter \u to 1.

Do note that these do need a whitespace character (linebreak or space) after them (or a \relax, but whitespace does the same) so the next command won't be ignored. For example,


does NOT print \u, but ignores the \the command.


\enddocument instead of \end{document} saves two characters

  • \$\begingroup\$ Doesn't seem to work for \begin{document} => \document though \$\endgroup\$ – sheß Mar 31 '19 at 12:21
  • 1
    \$\begingroup\$ \stop is even shorter and works often, too. \$\endgroup\$ – Skillmon Nov 2 '20 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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