15

I have some formula such as z_{(h_{1},h_{2},h_{3})} and z_{(h_{4},h_{5},h_{6})}. How can one introduce a \newcommand{}{} for all of such formulas?

Thanks in advance

  • 4
    Please confirm that the only things that differ between the two formulas are the level-two subscripts -- 1/2/3 vs. 4/5/6. Please also confirm that there are always exactly 3 items in the subscript position to the right of z. – Mico Sep 4 '17 at 19:15
  • 7
    @Mico: Very optimistic ;-) – user31729 Sep 4 '17 at 19:16
  • @Mico The difference is only in indices and they have always 3 items in subscript. – Fahim B Sep 4 '17 at 19:37
  • @FahimB: What about \zz{1} that produces z_{(h_{1},h_{2},h_{3})}? – Werner Sep 4 '17 at 19:54
1

They forgot xinttools.

\documentclass{article}

\usepackage{xinttools}

% Thank you very much. I will be very thankful if you write the commands for
% z_{j_{1}(h_{1},h_{2})} and z_{k(h_{3},h_{4},h_{5})}

\newcommand{\zz}[2]{z_{#1(\xintFor ##1 in {#2}\do {h_{##1}\xintifForLast{}{,}})}}
\begin{document}

\[ \zz{j_{1}}{1,2} = \zz{k}{3, 4, 5}\]

\end{document}

enter image description here

19
  \newcommand\zz[3]{z_{(h_{#1},h_{#2},h_{#3})} 

then you can use and \zz{1}{2}{3} and \zz{4}{5}{6} or even \zz123 and \zz456

  • 8
    +1. I was going to call the macro \zzz, to be mildly mnemonic of the fact that it takes 3 arguments... – Mico Sep 4 '17 at 19:43
  • 14
    @Mico and there was I being fearful of Ulrike chiding me for using too many z and you comment I have too few. I can't win. – David Carlisle Sep 4 '17 at 19:44
17

It's not difficult to extend it to any number of subscripts:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\zz}{m}
 {
  z
  \sp{}\sb
   {
    \clist_map_inline:nn { #1 }
     {
      \seq_put_right:Nn \l_fahim_z_subscripts_seq { h\sb{##1} }
     }
    (\seq_use:Nn \l_fahim_z_subscripts_seq { , })
   }
 }
\seq_new:N \l_fahim_z_subscripts_seq
\ExplSyntaxOff

\begin{document}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

\end{document}

enter image description here

This can be generalized to different base letters and different processing of the subscripts. The trailing optional argument sets how to treat each item in the comma separated list, see the examples.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\zz}{O{z}mO{h\sb{##1}}}
 {
  #1
  \sp{}\sb
   {
    \cs_set_protected:Nn \__fahim_z_subscript:n { #3 }
    \clist_map_inline:nn { #2 }
     {
      \seq_put_right:Nn \l_fahim_z_subscripts_seq { \__fahim_z_subscript:n { ##1 } }
     }
    (\seq_use:Nn \l_fahim_z_subscripts_seq { , })
   }
 }
\seq_new:N \l_fahim_z_subscripts_seq
\ExplSyntaxOff

\begin{document}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

$\zz[Z]{1,2,3}[k_{#1}]$

$\zz{1,2,3}[(#1)]$

\end{document}

enter image description here

For more complex settings, I suggest a key-value syntax. Here the keys are var (for the name of the variable), outer to set the overall setting (default is just adding the parentheses) and inner for the sequence of actual subscripts. See the given examples. At any moment you can issue \zzset to change (in the current scope) one or more of the values.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\zz}{O{}m}
 {
  \group_begin:
  \keys_set:nn { fahim/zz } { #1 }
  \fahim_zz:n { #2 }
  \group_end:
 }

\NewDocumentCommand{\zzset}{m}
 {
  \keys_set:nn { fahim/zz } { #1 }
 }

\keys_define:nn { fahim/zz }
 {
  var .tl_set:N = \l__fahim_zz_var_tl,
  outer .code:n = \cs_set_protected:Nn \__fahim_zz_outer:n { #1 },
  inner .code:n = \cs_set_protected:Nn \__fahim_zz_inner:n { #1 },
 }

\seq_new:N \l__fahim_zz_subscripts_seq

\cs_new_protected:Nn \fahim_zz:n
 {
  \tl_use:N \l__fahim_zz_var_tl
  \sp{} % a dummy superscript to lower the subscript
  \sb
   {
    \__fahim_zz_outer:n
     {
      \clist_map_inline:nn { #1 }
       {
        \seq_put_right:Nn \l__fahim_zz_subscripts_seq { \__fahim_zz_inner:n { ##1 } }
       }
      \seq_use:Nn \l__fahim_zz_subscripts_seq { , }
     }
   }
 }
\ExplSyntaxOff

% initialize
\zzset{
  var=z,
  outer=(#1),
  inner=h_{#1},
}

\begin{document}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

$\zz[var=Z,inner=k_{#1}]{1,2,3}$

$\zz[outer=i(#1)]{1,2,3}$

$\zz[outer=i(#1),inner=k_{#1}]{1,2,3}$

\end{document}

enter image description here

  • 4
    I've taken the liberty of adding a screenshot. :-) – Mico Sep 4 '17 at 20:04
  • Is it possible to use this method for formulas such as z_{i(h_{1},h_{2},h_{3})} and z_{k(h_{4},h_{5})}? – Fahim B Sep 12 '17 at 18:12
  • 1
    @FahimB The new version is online. – egreg Sep 12 '17 at 21:35
11

It's not difficult to extend it to any number of subscripts and without using ExplSyntaxOn:

\def\zz#1{\zzA#1,,}
\def\zzA#1,{z_\bgroup(h_{#1}\zzB}
\def\zzB#1,{\ifx\end#1\end)\egroup \else ,h_{#1}\expandafter\zzB\fi}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

\bye

EDIT If you need to add an ``index letter'' (i, j like in your comment), then it is possible to do using this code:

\def\zz#1#{z_\bgroup#1\zzI}
\def\zzI#1{\zzA#1,,}
\def\zzA#1,{(h_{#1}\zzB}
\def\zzB#1,{\ifx\end#1\end)\egroup \else ,h_{#1}\expandafter\zzB\fi}

$\zz i{1,2,3}+\zz j{4,5,6}=\zz{1,2,3,4,5,6}$

\bye
  • Is it possible to use this method for formulas such as z_{i(h_{1},h_{2})} and z_{j(h_{3},h_{4},h_{5})}? – Fahim B Sep 12 '17 at 19:19
  • @FahimB Yes, see above. – wipet Sep 12 '17 at 20:36
  • Thank you very much. I will be very thankful if you write the commands for z_{j_{1}(h_{1},h_{2})} and z_{k(h_{3},h_{4},h_{5})}. – Fahim B Sep 12 '17 at 20:54
  • 1
    OK: \zz j_1{1,2} and \zz k{3,4,5}. – wipet Sep 13 '17 at 4:10
4

Very easy with the listofitems package:

\documentclass{article}
\usepackage{listofitems}
\newcommand\zz[1]{
  z_{(
    \setsepchar{,}
    \readlist*\zlist{#1}
    \foreachitem\i\in\zlist{\ifnum\icnt=1\relax\else,\fi h_{\i}}
  )}
}
\begin{document}
$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$
\end{document}

enter image description here

By the way, listofitems works in plain TeX, as well:

\input listofitems.tex
\def\zz#1{
  z_{(
    \setsepchar{,}
    \readlist*\zlist{#1}
    \foreachitem\i\in\zlist{\ifnum\icnt=1\relax\else,\fi h_{\i}}
  )}
}
$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$
\end
2

You could also use e-TeX. (It seems rather simple to me.) Assuming that you have three subsequent indices every time you would say

\newcommand*\zz[1]{%
  \@tempcnta\numexpr#1+1\relax
  \@tempcntb\numexpr#1+2\relax
  z_{(%
    h_{#1}+h_{\the\@tempcnta}+h_{\the\@tempcntb}%
  )}
}

and then call \zz{1} resp. \zz{4}.

output_solution1

To add in a few generalisations, i.e. arbitrary number of indices and specified indices is not a big deal:

\newcommand*\zzz[2][h]{%
  \def\forplus{\def\forplus{+}}
  z_{(%
    \@for\i:=#2\do{\forplus#1_{\i}}%
  )}
}

Note the optional parameter for the subscripts of first order:

\begin{gather*}
  \zzz{1,2,3}\\
  \zzz{4,5,6}\\
  \zzz[p]{7,11,13,17}
\end{gather*}

output_solution2

If you want to you can get really sophisticated by declaring something that acts like

\indexloop[<delimiter>][<format>]{<indices>}

where <format>:='<superscript>_<opt. delimiter><subscript><opt. delimiter>'

defined by

\makeatletter
\def\defaultsup{z}
\def\defaultsub{h}
\def\defaultdll{(}
\def\defaultdlr{)}
\def\defaultsep{+}
\def\indexloop{%
  \kernel@ifnextchar[
    {\indexl@op}
    {\indexl@op[\defaultsup_\defaultdll\defaultsub\defaultdlr]}
}
\def\indexl@op[#1]{%
  \kernel@ifnextchar[
    {\indexl@@p[{#1}]}
    {\indexl@@p[\defaultsep][{#1}]}
}
\def\indexl@@p[#1][#2]#3{%
  \def\forsep{\def\forsep{#1}}
  \def\customsup{}
  \def\customsub{}
  \def\customdll{}
  \def\customdlr{}
  \process@format#2\@end
  \customsup_{%
    \customdll
    \@for\i:=#3\do{\forsep\customsub_{\i}}%
    \customdlr
  }%
}
\def\process@format#1_#2\@end{%
\def\customsup{#1}
\process@sub#2\@@end
}
\def\process@sub#1{
\ifx#1\@@end\else
  \ifcat#1x
    \edef\customsub{\customsub#1}
  \else
    \ifx\customdll\@empty
      \def\customdll{#1}
    \else
      \ifx\customdlr\@empty
        \def\customdlr{#1}
      \fi
    \fi
  \fi
  \expandafter\process@sub
\fi
}
\makeatother

Here is a short test of the last solution.

\begin{gather*}
  \indexloop{1,2,3}\\
  \indexloop{4,5,6}\\
  \indexloop[z_(p)]{7,11,13,17}\\
  \indexloop[-][z_\langle x\rangle]{8,9,10,12,14,15,16}\\
  \indexloop[,][{a_[i]}]{1,2}
\end{gather*}

output_solution3

Complete Code

% arara: pdflatex
\documentclass{article}
\usepackage{amsmath}

\makeatletter
\newcommand*\zz[1]{%
  \@tempcnta\numexpr#1+1\relax
  \@tempcntb\numexpr#1+2\relax
  z_{(%
    h_{#1}+h_{\the\@tempcnta}+h_{\the\@tempcntb}%
  )}
}
\newcommand*\zzz[2][h]{%
  \def\forplus{\def\forplus{+}}
  z_{(%
    \@for\i:=#2\do{\forplus#1_{\i}}%
  )}
}
\def\defaultsup{z}
\def\defaultsub{h}
\def\defaultdll{(}
\def\defaultdlr{)}
\def\defaultsep{+}
\def\indexloop{%
  \kernel@ifnextchar[
    {\indexl@op}
    {\indexl@op[\defaultsup_\defaultdll\defaultsub\defaultdlr]}
}
\def\indexl@op[#1]{%
  \kernel@ifnextchar[
    {\indexl@@p[{#1}]}
    {\indexl@@p[\defaultsep][{#1}]}
}
\def\indexl@@p[#1][#2]#3{%
  \def\forsep{\def\forsep{#1}}
  \def\customsup{}
  \def\customsub{}
  \def\customdll{}
  \def\customdlr{}
  \process@format#2\@end
  \customsup_{%
    \customdll
    \@for\i:=#3\do{\forsep\customsub_{\i}}%
    \customdlr
  }%
}
\def\process@format#1_#2\@end{%
\def\customsup{#1}
\process@sub#2\@@end
}
\def\process@sub#1{
\ifx#1\@@end\else
  \ifcat#1x
    \edef\customsub{\customsub#1}
  \else
    \ifx\customdll\@empty
      \def\customdll{#1}
    \else
      \ifx\customdlr\@empty
        \def\customdlr{#1}
      \fi
    \fi
  \fi
  \expandafter\process@sub
\fi
}
\makeatother

\begin{document}
\begin{gather*}
  \zz{1}\\
  \zz{4}
\end{gather*}

\begin{gather*}
  \zzz{1,2,3}\\
  \zzz{4,5,6}\\
  \zzz[p]{7,11,13,17}
\end{gather*}

\begin{gather*}
  \indexloop{1,2,3}\\
  \indexloop{4,5,6}\\
  \indexloop[z_(p)]{7,11,13,17}\\
  \indexloop[-][z_\langle x\rangle]{8,9,10,12,14,15,16}\\
  \indexloop[,][{a_[i]}]{1,2}
\end{gather*}
\end{document}

Edit

Even the first solution can be more sophisticated by implementing the step length:

\newcommand*\zz[2][1]{%
  \@tempcnta\numexpr#2+1*#1\relax
  \@tempcntb\numexpr#2+2*#1\relax
  z_{(%
    h_{#2}+h_{\the\@tempcnta}+h_{\the\@tempcntb}%
  )}
}

\[\zz[2]{0}\] would then compile to z_{h_0+h_2+h_4} as expected.

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.