14

Currently, I have a macro \bigseq which takes a variable name and a last number and produces #1_{1},#1_{2},\ldots,#1_{#2}, and for example x_{1},x_{2},\ldots,x_{n}.

Now, sometimes I want to produce a full sequence when given specific numbers. I would like a macro \seq that takes a first and last index and outputs the entire sequence. For example, for 3 and 7, I want to get x_{3},x_{4},x_{5},x_{6},x_{7}. Is that possible?

1

3 Answers 3

11
\documentclass[a4paper]{article}
\usepackage{etoolbox}
\newcommand{\bigseqx}[3]{{#1_{#2}%
  \count255=\numexpr#2\relax
  \whileboolexpr{ test {\ifnumcomp{\count255}{<}{\numexpr#3\relax}}}
    {\advance\count255 by 1 ,#1_{\number\count255 }}%
}}

\begin{document}
$\bigseqx{x}{3}{7}$
\end{document}

Some explanations. We use the \whileboolexpr macro of etoolbox (there are other packages that offer similar functionality); it takes two arguments: the first one is a test introduced by the test keyword, followed by the actual test, so we'll execute the code in the second argument as long as the test evaluates as true. But before starting this loop, we typeset the first element of the sequence and set a temporary counter to the second argument to \bigseqx (the first one is the symbol for the variable). The code increments the counter and typesets a comma and the next subscripted variable. The test evaluates as false when the counter becomes equal to the third argument.

We set the temporary counter to a value computed by \numexpr and use again \numexpr for comparing the counter to the third argument, so input such as

\bigseqx{x}{\value{cnt}}{\value{cnt}+9}

(where cnt is a LaTeX counter) is valid; \numexpr\value{cnt}+9\relax evaluates the expression (and the \relax token is swallowed because it's simply a terminator for the numeric expression).


Note: at the moment I wrote the answer I wasn't using expl3.

It's even shorter with expl3

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\bigseqx}{mmm}
 {
  #1\sb{#2}
  \int_step_inline:nnnn { #2+1 } { 1 } { #3 }
   {
    , #1\sb{##1}
   }
 }
\ExplSyntaxOff
\begin{document}

$\bigseqx{x}{3}{7}$

\end{document}

The idea is the same as above, but the working should be clearer: we print the first element, then a comma and the next element until we're finished. The key point is \int_step_inline:nnnn that takes as arguments the starting point, the step, the final point and the action to perform, in which we can refer to the current value by #1 (it's ##1 because \int_step_inline:nnnn is used in a definition). Each of the first three arguments can be an integer expression using any of the math facilities of expl3.

4
  • This is hardly understandable, plus it won't run with my texlive here, should I say the code is wrong ?
    – MP0
    May 10, 2011 at 10:02
  • 1
    @Eeva --- you should not say that egreg's code is wrong, because it is not. @egreg --- perhaps you could add a sentence or two explaining the purpose of the two \relax commands here. May 10, 2011 at 12:23
  • @Eeva, check if you have a recent installation, perhaps? May 10, 2011 at 18:18
  • @Bruno Le Floch, will do, sorry about the previous comment.
    – MP0
    May 11, 2011 at 9:11
3

Here the adjusted form of my answer to Writing a macro to typeset a variable number of terms of a series, which now allows for a user-defined minimal index. It is fully expandable, except of the robust \ensuremath which can be removed if required.. Use it like \seq{<var>}{<min>}{<max>}, e.g. \seq{x}{3}{7}.

\documentclass{article}

\usepackage{amsmath}

\newcommand*{\seq}[3]{% #1 = variable, #2/#3 = min./max. number of terms
    \ensuremath{%
    \ifnum#2<0 \else
        #1_{#2}\expandafter\seqx\expandafter{\the\numexpr#2+1\relax}{#3}{#1}%
    \fi
    }%
}

% Internal recursive macro
\newcommand*{\seqx}[4]{% #1 = current index, #2 = max index, #3 = variable, #4 = \fi
    #4% = \fi
    \ifnum#1>#2 \else
        +#3_{#1}%
        \expandafter\seqx\expandafter{\the\numexpr#1+1\relax}{#2}{#3}%
    \fi
}

\begin{document}

\seq{x}{1}{10}

\seq{x}{3}{7}

\end{document}
4
  • that #4=\fi is very nice. I wouldn't use braces around #1 in \seq and #3 in \seqx, as this won't give correct results for \seq{x'}{1}{8}. And, of course, I wouldn't use \ensuremath. :-)
    – egreg
    May 10, 2011 at 22:27
  • @egreg: You are right about the braces, but why not use \ensuremath? May 10, 2011 at 22:30
  • @egreg: Ok, I just figured that \ensuremath is robust and will add some extra stuff in an \edef context to the otherwise fully expandable macro. But that feature isn't that important anyway in this application. May 10, 2011 at 22:37
  • my opinion is that math should be confined in math environments. It's very rare that a command benefits from \ensuremath. But that's just an opinion.
    – egreg
    May 10, 2011 at 23:18
1

I guess you could also do that with the \forloop package, below is a small example:

\documentclass{report}
\usepackage{forloop}
\begin{document}
\newcounter{themenumber}
\newcommand{\seq}[2]
{%
\forloop{themenumber}{#1}{\value{themenumber} < #2}{%
    $ x_{\arabic{themenumber}}, $%
}%
}

\seq{2}{6}
\end{document}
4
  • Well, the end number needs to be fixed, and a test is to be added to remove the last coma. Sorry for that, but the main idea is here
    – MP0
    May 10, 2011 at 9:43
  • The code is wrong in many aspects. You are wasting a counter for each call of \seq, for example. And there's a trailing comma, with wrong spacing after inner commas.
    – egreg
    May 10, 2011 at 9:45
  • You're right, I moved the counter out of the newcommand.
    – MP0
    May 10, 2011 at 9:49
  • @egreg: I find it readable, and the point is made.
    – MP0
    May 10, 2011 at 10:00

You must log in to answer this question.

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