[Tex/LaTex] Increment loop variable in inner foreach loop

foreachpgfmathtikz-pgf

I need the following pairs of numbers:
12 13 14
23 24
34

My first attempt was to use two nested foreach loops:

\foreach \x in {1,...,4} {
  \foreach \y in {\x+1,...,4} { % This would be very easy in LuaTeX
    \node at (\x,\y) {(\x,\y)};
  }
}

But TikZ or LaTeX interprets the + in \x+1 not like a arithmetic operation, but as a string. So 1+2 is not interpreted as 3, but as a string 1+2.

I am sure there must be a way to generate the above sequence of pairs of number, but I don't know how. I am also tempted to switch to LuaTeX or LuaLaTeX, because such loops are very easy to handle in a general programming language.

Best Answer

You're right, it's a bit of a shame that the expressions aren't evaluated before the loop is started.

Three approaches:

Use the count=\xi expression to make the outer loop counter accessible. In this case, the outer loop only has to run from 2 to 4, while the counter will run from 1 to 3, which happens to be the starting point of the inner loop. This solution only works in this special case, though, as soon as you need the inner loop to be larger by a different value, you'll have to resort to something else.

Alternatively, you can parse the expression at the start of the outer loop using \pgfmathtruncatemacro, which will save the result as an integer, or using the evaluate=\x as \result using <expression> syntax.

Note that the outer loop actually only needs to run from 1 to 3.

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\foreach \x [count=\xi] in {2,...,4} {
  \foreach \y  in {\x,...,4} {
    \node at (\xi,\y) {(\xi,\y)};
  }
}
\end{tikzpicture}

\begin{tikzpicture}
\foreach \x in {1,...,3} {
    \pgfmathtruncatemacro\ystart{\x+1}
    \foreach \y in {\ystart,...,4} {
      \node at (\x,\y) {(\x,\y)};
    }
}
\end{tikzpicture}

\begin{tikzpicture}
\foreach \x [evaluate=\x as \ystart using int(\x+1)] in {1,...,3} {
    \foreach \y in {\ystart,...,4} {
      \node at (\x,\y) {(\x,\y)};
    }
}
\end{tikzpicture}
\end{document}