3

I need a nested loop to animate PSTricks diagrams. In C# or C or C++, I usually write as follows.

int N=6;
for(int x=0; x<N; x++)
    for(int y=x+1; y<N; y++)
        Console.WriteLine("({0}, {1})",x,y);

I have attempted to do it in TeX as follows, but it does not work. :-)

\documentclass{minimal}
\usepackage{multido}

\newcommand\N{6}
\newcommand\Init{}
\newcommand\Freq{}
\begin{document}
\multido{\ix=0+1}{\N}
{
        \makeatletter
            \renewcommand\Init{\strip@pt\dimexpr\ix pt + 1pt\relax}         
            \renewcommand\Freq{\strip@pt\dimexpr\N pt - \Init pt\relax}
        \makeatother
        \multido{\iy=\Init+1}{\Freq}
        {
                (\ix, \iy)\par
        }
}
\end{document}

How to fix it?

4 Answers 4

6
\documentclass{minimal}
\usepackage{multido}

\newcommand\N{6}
\begin{document}
\multido{\ix=0+1,\ixB=1+1,\iN=5+-1}{\N}{%
  \multido{\iy=\ixB+1}{\iN}{(\ix, \iy)\endgraf}}
\end{document}

and with a counter:

\documentclass{minimal}
\usepackage{multido}
\newcommand\N{6}
\newcounter{NminusOne}
\setcounter{NminusOne}{\N}\addtocounter{NminusOne}{-1}

\begin{document}
\multido{\ix=0+1,\ixB=1+1,\iN=\theNminusOne+-1}{\N}{%
  \multido{\iy=\ixB+1}{\iN}{(\ix, \iy)\endgraf}}
\end{document}
4
  • Is there a trick to avoid hard-coding the value 5? Commented Jul 23, 2011 at 21:13
  • define two counters for N and NminusOne, then you can use these instead of \N and 5
    – user2478
    Commented Jul 23, 2011 at 21:22
  • @Herbert: It seems useful to define \multido as a long macro. Is there any special reason that \multido isn't a long macro? If not, could you revise it to support \par?
    – Leo Liu
    Commented Jul 23, 2011 at 21:36
  • @Leo: it is a really old package and only bug fixes will be done. Too many people use it in the meantime, modifications to the code may be dangerous. You can use \endgraf instead and all is fine.
    – user2478
    Commented Jul 23, 2011 at 21:48
1

You need to use \edef to expand the macro content. Using \renewcommand simply redefines the macro to the exact same content over and over again. That the \ix and \Init macros have a changing value doesn't matter here. You can't have a paragraph in \multido because it isn't defined \long. So use either \\ or hide the \par in a macro. You need also take care of spaces introduced by line breaks, e.g. after } and {. The \makeatletter and \makeatother macros must be places outside the \multido macro, otherwise it's already to late to change catcodes.

\documentclass{minimal}
\usepackage{multido}

\newcommand\N{6}
\newcommand\Init{}
\newcommand\Freq{}
\newcommand\mypar{\par}
\begin{document}
\makeatletter
\multido{\ix=0+1}{\N}{%
    \edef\Init{\strip@pt\dimexpr\ix pt + 1pt\relax}%
    \edef\Freq{\strip@pt\dimexpr\N pt - \Init pt\relax}%
    \multido{\iy=\Init+1}{\Freq}{%
        (\ix, \iy)\mypar
    }%
}
\makeatother
\end{document}
4
  • where is the sense to use \dimexpr when the unit is not needed?
    – user2478
    Commented Jul 23, 2011 at 20:58
  • Thank you for your answer. Especially introducing me to \edef. It might be used in another scenario in my life. :-) Since Herbert's solution is simpler than yours so I switched the green mark to Herbert's. Commented Jul 23, 2011 at 21:01
  • @Herbert: I didn't changed that part of xport's original code, simply fixed the other issues. The code works beside that. Commented Jul 23, 2011 at 21:02
  • @xport: That's fine. You shouldn't accept answers right away anyway. Commented Jul 23, 2011 at 21:02
0

The following is the simplified version of Herbert's answer.

\documentclass{minimal}
\usepackage{multido}
\newcommand\N{6}


\newcounter{NTemp}
\setcounter{NTemp}{\N}

\begin{document}
\multido{\ix=0+1,\iTemp=1+1}{\N}
{
  \addtocounter{NTemp}{-1}
  \multido{\iy=\iTemp+1}{\theNTemp}
  {
    (\ix, \iy)\endgraf
  }
}
\end{document}
0
\documentclass{minimal}
\usepackage{multido}


\newcommand{\N}{6}
\newcounter{Init}
\newcounter{Freq}
\setcounter{Freq}{\N}
\newcommand\mypar{\par}

\begin{document}
\multido{\ix=0+1}{\N}
{
    \setcounter{Init}{\ix}
    \addtocounter{Init}{1}
    \addtocounter{Freq}{-1}
    \multido{\iy=\value{Init}+1}{\value{Freq}}
    {
        (\ix, \iy)\endgraf
    }
}
\end{document}
1
  • see edited answer
    – user2478
    Commented Jul 23, 2011 at 21:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .