11

I need a simple latex macro which takes some format and creates a sequence out of it. For example,

\macro[N]{x^N y^N} => x^1 y^1 + x^2 y^2 + \dots + x^N y^N
\macro[N]{x^N y_N} => x^1 y_1 + x^2 y_2 + \dots + x^N y_N
\macro[N]{(x^N y_N)^2} => (x^1 y_1)^2 + (x^2 y_2)^2 + \dots + (x^N y_N)^2

enter image description here

1
  • 1
    Welcome! (And nice question, although I think I've seen a duplicate, but I'm unable to find it on the spot...). Just a question: what should happen if N≤2?
    – Rmano
    Mar 17, 2023 at 8:56

7 Answers 7

6

If you are willing to write \N for the symbol to be replaced, I can offer the following solution.

\documentclass{article}
\usepackage{amsmath}

\newcommand{\macro}[2][]{
    \def\N{1} #2
    +
    \def\N{2} #2
    +\cdots+
    \def\N{#1} #2
}

\begin{document}
    \verb|\macro[N]{x^\N y^\N}| gives $\macro[N]{x^\N y^\N}$

    \bigskip\verb|\macro[N]{x^\N y_\N}| gives $\macro[N]{x^\N y_\N}$

    \bigskip\verb|\macro[M]{(x^\N y_\N)^2}| gives $\macro[M]{(x^\N y_\N)^2}$
\end{document}

Result

9

You can define an auxiliary macro and do the replacement.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\makesum}{O{N}m}
 {
  \akkapelli_makesum:nn { #1 } { #2 }
 }

\tl_new:N \l__akkapelli_makesum_template_tl
\cs_generate_variant:Nn \cs_set_protected:Nn { NV }

\cs_new_protected:Nn \akkapelli_makesum:nn
 {
  \tl_set:Nn \l__akkapelli_makesum_template_tl { #2 }
  \tl_replace_all:Nnn \l__akkapelli_makesum_template_tl { #1 } { {##1} }
  \cs_set_protected:NV \__akkapelli_makesum_do:n \l__akkapelli_makesum_template_tl
  \__akkapelli_makesum_do:n { 1 } + \__akkapelli_makesum_do:n { 2 } + \dots + \__akkapelli_makesum_do:n { #1 }
 }

\ExplSyntaxOff

\begin{document}

$\makesum{x^Ny^N}$

$\makesum{x^Ny_N}$

$\makesum[M]{(x^M y_M)^2}$

\end{document}

The optional argument (default N) is substituted in the second argument with #1, so we can define a macro based on it and use it.

enter image description here

However, I'd prefer a different approach: in the second argument you use #1 for the “variable part”:

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\makesum}{O{N}m}
 {
  \akkapelli_makesum:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \akkapelli_makesum:nn
 {
  \cs_set_protected:Nn \__akkapelli_makesum_do:n { #2 }
  \__akkapelli_makesum_do:n { 1 } + \__akkapelli_makesum_do:n { 2 } + \dots + \__akkapelli_makesum_do:n { #1 }
 }

\ExplSyntaxOff

\begin{document}

$\makesum{x^#1y^#1}$

$\makesum{x^#1y_#1}$

$\makesum[M]{(x^#1 y_#1)^2}$

$\makesum[100]{(x^{#1} y_{#1})^2}$

\end{document}

Note the necessary braces in the last case.

enter image description here

If integer exponents are used, it is better to cope with the “small” cases.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\makesum}{O{N}m}
 {
  \akkapelli_makesum:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \akkapelli_makesum:nn
 {
  \cs_set_protected:Nn \__akkapelli_makesum_do:n { #2 }
  \regex_match:nnTF { \A [0-9]* \Z } { #1 }
   {% numeric argument
    \int_case:nnF { #1 }
     {
      {0}{0}
      {1}{\__akkapelli_makesum_do:n { 1 }}
      {2}{\__akkapelli_makesum_do:n { 1 } + \__akkapelli_makesum_do:n { 2 }}
      {3}{\__akkapelli_makesum_do:n { 1 } + \__akkapelli_makesum_do:n { 2 } + \__akkapelli_makesum_do:n { 3 }}
     }
     { \__akkapelli_makesum_generic:n { #1 } }
   }
   { \__akkapelli_makesum_generic:n { #1 } }
 }

\cs_new_protected:Nn \__akkapelli_makesum_generic:n
 {
  \__akkapelli_makesum_do:n { 1 } + \__akkapelli_makesum_do:n { 2 } + \dots + \__akkapelli_makesum_do:n { #1 }
 }

\ExplSyntaxOff

\begin{document}

$\makesum{x^#1y^#1}$

$\makesum{x^#1y_#1}$

$\makesum[M]{(x^#1 y_#1)^2}$

$\makesum[1]{x^{#1} y_{#1}}$

$\makesum[2]{x^{#1} y_{#1}}$

$\makesum[3]{x^{#1} y_{#1}}$

$\makesum[4]{x^{#1} y_{#1}}$

$\makesum[100]{(x^{#1} y_{#1})^2}$

\end{document}

enter image description here

6
  • Nice property + solution.
    – MS-SPO
    Mar 17, 2023 at 12:33
  • Now \makesum[1]{(x^{#1} y_{#1})^2} and \makesum[2]{(x^{#1} y_{#1})^2} are going to look at bit funny.
    – Gaussler
    Mar 17, 2023 at 13:45
  • @Gaussler Yes, of course, but that's not what the OP has in mind, I believe.
    – egreg
    Mar 17, 2023 at 14:39
  • No, you’re right, but still, makes Friday night a bit more entertaining.
    – Gaussler
    Mar 17, 2023 at 16:11
  • 2
    @Gaussler Enjoy the Saturday's update.
    – egreg
    Mar 18, 2023 at 10:00
6

This solution is a purely (e-)TeX one. It uses the same idea as Οὖτις's, but it doesn't require that the input be a control sequence (the input must be a character). I got rid of the optional argument because I dont understand its purpose, but if it was intended as egreg used it, you can simply change the \def to a \newcommand whose optional argument is by default N.

\def\macro#1#2{{%
    \everyeof={}%                   So nothing weird happens at the end of \scantokens
    \catcode`#1=\active%            Make the parameter an active character
    \scantokens{%                   Retokenize the following code so that #1's catcode is changed
        \def#1{1}#2\def#1{2}+#2%    Print a_1+a_2
    }%
    +\cdots+#2%                     Print +...+a_N
}}

$$\macro{N}{x^Ny^N}$$
$$\macro{N}{x^Ny_N}$$
$$\macro{M}{(x^My_M)}$$

Gives:

macro usage

5

You did not tell whether with the result of \macro the focus is on obtaining the set of tokens, e.g., for defining another macro from it, or is on obtaining some nice typesetting in the pdf file.

If you just need some nice typesetting in the pdf-file, and if the LaTeX-distribution used by you is up to date, then probably some regexp-replacing via the function \regexp_replace_all:nnN of expl3's l3regexp-package does what you need:

\documentclass{article}

\ExplSyntaxOn
\cs_new_protected:Npn \macro [#1] #2 {
   \group_begin:
      \tl_set:Nn \l_tmpa_tl {#2}
      \group_begin: 
         \regex_replace_all:nnN {#1} {1} \l_tmpa_tl 
         \l_tmpa_tl 
      \group_end:
      +
      \group_begin:
         \regex_replace_all:nnN {#1} {2} \l_tmpa_tl 
         \l_tmpa_tl 
      \group_end: 
      + \dots +
       \regex_replace_all:nnN {#1} {\cB\{#1\cE\}} \l_tmpa_tl 
       \l_tmpa_tl 
   \group_end:
}
\ExplSyntaxOff

\begin{document}

% \( causes LaTeX to switch to inline math mode.
% \) causes LaTeX to switch back to whatever typesetting it was in before
%    switching to inline math took place.

\verb|\(\macro[N]{x^N y^N}\)| yields: \(\macro[N]{x^N y^N}\)

\verb|\(\macro[N]{x^N y_N}\)| yields: \(\macro[N]{x^N y_N}\)

\verb|\(\macro[M]{(x^M y_M)^2}\)| yields: \(\macro[M]{(x^M y_M)^2}\)

\verb|\(\macro[Moo]{(x^Moo y_Moo)^2}\)| yields: \(\macro[Moo]{(x^Moo y_Moo)^2}\)

\end{document}

enter image description here


Be aware that using argument-delimiters [ and ] (square brackets) for macro arguments which must be provided with each call/instance of the macro in question actually is considered very bad practise in LaTeX. This deviates from usual syntax in LaTeX - in LaTeX usually only optional macro arguments, i.e., arguments which you don't need to provide with each call/instance of the macro in question, are to be nested between [ and ].

This time I did it this way in order for the code to comply to your requests.

3

What about this?

\documentclass{article}
\usepackage{pgffor}

\newcommand{\macro}[2]{%
  \foreach \n in {1,...,#1}{%
    #2%
    \ifnum\n<#1 + \fi
  }%
}

\begin{document}

$\macro{5}{x^\n y^\n}$

$\macro{5}{(x^\n y_\n)^2}$

\end{document}

enter image description here

2

You are almost there. A few remarks:

  • macros are called \newcommand in LaTeX
  • you can't name them the way you did
  • instead, use simple terms using characters only (no digits, _ etc.)
  • the first parameter [1] indicates the number of parameters passed, later accessed as parmeter #1 (i.e. #2, #3 etc. if you pass more)
  • I used math-mode $ $ inside, but that depends on the context you'll use your macro in
  • LaTeX just expands the the content of #1 character by character ... that's why I needed to use {#1} inside to "break this"

Find more on macros in this wikibook. Which makes me aware of using \ensuremath, see there.

result

\documentclass[10pt]{article}

\newcommand\A[1]{$x^1 y^1 + x^2 y^2 + \dots + x^{#1} y^{#1}$}
\newcommand\B[1]{$x^1 y_1 + x^2 y_2 + \dots + x^{#1} y_{#1}$}
\newcommand\C[1]{$(x^1 y_1)^2 + (x^2 y_2)^2 + \dots + (x^{#1} y_{#1})^2$}


\begin{document}

\A{13}
\bigskip

\B{-33}
\bigskip

\C{123}

\end{document}

1
0

A Lua solution:

\documentclass{article}
\usepackage{amsmath}
\usepackage{luacode}

\begin{luacode*}
    function makesum(placeholder, template)
        tex.print(
            template:gsub(placeholder, "1") .. "+" ..
            template:gsub(placeholder, "2") ..  [[+ \dots + ]] .. template)
    end
\end{luacode*}

\ExplSyntaxOn

\NewDocumentCommand\makesum {O{N} m} {
    \directlua{makesum("\luaescapestring{\unexpanded{#1}}", "\luaescapestring{\unexpanded{#2}}")}
}
% we need \unexpanded here to preserve the fragile and old-style robust commands because \luaescapestring fully expands the argument without doubling '#', see https://tex.stackexchange.com/a/638779/250119 for list of common Lua functions for manipulation

\ExplSyntaxOff

\begin{document}

$\makesum{x^Ny^N}$

$\makesum{\vec{x}^Ny^N}$

$\makesum{x^Ny_N}$

$\makesum[M]{(x^M y_M)^2}$

\end{document}

This uses string.gsub without "proper" escaping, so ensure % does not appear in the placeholder or the template (see https://stackoverflow.com/questions/9790688/escaping-strings-for-gsub for workarounds).

output image

You must log in to answer this question.

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