# Possible to generate sequences given term, length, start and end?

I'm in a computer science formal languages / computability / complexity course, and I have to type a lot of sequences... Sometimes I have to edit the terms, add terms, remove terms, etc., and doing it by hand seems messy.

Is it possible to generate a sequence of terms (not necessarily numbers) with subscripts automatically, given perhaps the term label and length of sequence for starters, and then possible additional options like: step, which terms to include, commas/spaces, etc.?

Basically, I want something like this:

From perhaps something like this:

\seq{a}{1..2n}{1,3,2}
Skip(L)=\{~\seq{a}{1..2n-1}{2,2,1} ~|~ \seq{a}{1..2n}{1,3,2} \text{ is in } L~\}


Instead of having to write this:

a_1~a_2~a_3~\ldots~a_{2n-1}~a_{2n}
Skip(L)=\{~a_1~a_3~\ldots~a_{2n-1} ~|~ a_1~a_2~a_3~\ldots~a_{2n-1}~a_{2n} \text{ is in } L~\}


Maybe there is a discrete math or formal languages package specifically that can do this? I'm Googling, but haven't found what I'm looking for yet.

• What does each argument do? I mean \seq{a}{1...2n} seems logical for me, what do the other arguments do? – Manuel Feb 1 at 23:32
• @Manuel Those extra arguments might be for specifying number of specified starting terms and number of ending terms, e.g. {2,1} And the other argument was for a maybe a step, e.g. every term {1}, or every other term {2}, etc. Don't know if anything like that exists though... – delrocco Feb 1 at 23:41
• @delrocco Can we assume you will always only input 1 item, three dots, and last item? Or you want more flexibility? – Manuel Feb 1 at 23:44
• @Manuel The number of terms at start and end of sequence are not critical I'd say to most sequences, and a good start if you have a solution for that. I'm using my professor specific sequences here in his notes/homeworks. Also, I could see sequences when they would be critical. – delrocco Feb 1 at 23:44

Syntax: \seq[⟨steps before ellipsis⟩,⟨steps after ellipsis⟩]{⟨term label⟩}[⟨step⟩]{⟨first index⟩,...,⟨last index⟩} where every [..] is optional.

\documentclass{scrartcl}

\usepackage{mathtools,amssymb}
\DeclareMathOperator\Skip{Skip}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \seq { o m o m }
{
\group_begin:
\IfValueT {#1}
{
\int_set:Nn \l_delrocco_ini_int { \clist_item:nn {#1} {1} }
\int_set:Nn \l_delrocco_fin_int { \clist_item:nn {#1} {2} }
}
\IfValueT {#3}
{
\int_set:Nn \l_delrocco_step_int { #3 }
}
\delrocco_seq:nn { #2 } { #4 }
\group_end:
}

\int_new:N  \l_delrocco_ini_int
\int_set:Nn \l_delrocco_ini_int  { 3 }
\int_new:N  \l_delrocco_fin_int
\int_set:Nn \l_delrocco_fin_int  { 2 }
\int_new:N  \l_delrocco_step_int
\int_set:Nn \l_delrocco_step_int { 1 }

\cs_set_eq:NN \math_sb:n \sb

\cs_new_protected:Npn \delrocco_seq:nn #1 #2
{
\int_step_inline:nnnn
{ \clist_item:nn {#2} {1} }
{ \l_delrocco_step_int }
{ \clist_item:nn {#2} {1} + (\l_delrocco_ini_int - 1) * \l_delrocco_step_int }
{ #1 \math_sb:n { ##1 } \, }
\!\cdots
\int_step_inline:nnnn
{ (\l_delrocco_fin_int - 1) * \l_delrocco_step_int }
{ -\l_delrocco_step_int }
{ \l_delrocco_step_int }
{ #1 \math_sb:n { \clist_item:nn {#2} {3} - ##1 } \, }
#1 \math_sb:n { \clist_item:nn {#2} {3} }
}
\ExplSyntaxOff

\begin{document}
$\seq[4,4]{a}[2]{5,...,2n}$
$\Skip(L) = \{ \seq[2,1]{a}{1,...,2n-1} \mid \seq{a}{1,...,2n} \in L \}$
\end{document}


If you don't want the spaces remove every instance of \, and \!.

• This is nice! I'm customizing it a bit. I take it there is no standard package for doing formal language stuff like this? – delrocco Feb 2 at 0:37
• I modified it so all the optionals are in one array, and the default start and end number of terms is 1. So you use it like \seq[3,3,2]{a}{1,...,2n} or \seq{a}{3,...,2n-3}. Thank you very much for your response! – delrocco Feb 2 at 1:05
• The thing with my solution was that you could change separately the step or the other without needing to input everything. But ok! – Manuel Feb 2 at 8:28
• Yea I noticed that. Your solution is more general. I figured most of the time I would be supplying the start and end terms only if modifying the step, so I just threw it all into one optional argument - but that may turn out to be incorrect lol We'll see ~ – delrocco Feb 3 at 4:45

With some pain in programming it, the following macros seem to do what you like with a not very complicated syntax.

\seq{<variable>}{<start>..<end>}[<initial>,<final>,<step>]


where <final> and <step> can be omitted and are both set to 1 in this case. If the optional argument is missing, [2,1,1] is implied.

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\seq}
{
m                               % base letter
>{\SplitArgument{1}{..}}m       % <start>..<stop>
>{\SplitArgument{2}{,}}O{2,1,1} % <initial>,<final>,<step>
}
{
\delrocco_seq_print:nnnnnn { #1 } #2 #3
}

\cs_new_protected:Nn \delrocco_seq_print:nnnnnn
{
\tl_if_novalue:nTF { #5 }
{
\__delrocco_seq_print:nnnnnn { #1 } { #2 } { #3 } { #4 } { 1 } { 1 }
}
{
\tl_if_novalue:nTF { #6 }
{
\__delrocco_seq_print:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { 1 }
}
{
\__delrocco_seq_print:nnnnnn { #1 } { #2 } { #3 } { #4 } { #5 } { #6 }
}
}
}

\cs_new_protected:Nn \__delrocco_seq_print:nnnnnn
{
\mathopen{}
\int_step_inline:nnnn { #2 } { #6 } { #2+(#4-1)*#6 }
{ \mathbin{}\nobreak #1\sb{##1} }
\mathbin{}\nobreak\dots
\__delrocco_seq_break:n { #3 }
\int_step_inline:nnnn { 0-(#5-1)*#6 } { #6 } { 0 }
{
\mathbin{}\nobreak
#1\sb
{
\l__delrocco_seq_base_tl
\int_compare:nTF { \l__delrocco_seq_index_int + (##1) < 0 }
{
\int_to_arabic:n { \l__delrocco_seq_index_int + (##1) }
}
{
\int_compare:nF { \l__delrocco_seq_index_int + (##1) = 0 }
{
\tl_if_empty:NF \l__delrocco_seq_base_tl { + }
\int_to_arabic:n { \l__delrocco_seq_index_int + (##1) }
}
}
}
}
\mathclose{}
}

\seq_new:N \l__delrocco_seq_temp_seq
\tl_new:N \l__delrocco_seq_temp_tl
\tl_new:N \l__delrocco_seq_base_tl
\int_new:N \l__delrocco_seq_index_int

\cs_new_protected:Nn \__delrocco_seq_break:n
{
\regex_split:nnN { ([\+\-]?[0-9]+\Z) } { #1 } \l__delrocco_seq_temp_seq
% the last item is empty if there is a base and an index
\seq_pop_right:NN \l__delrocco_seq_temp_seq \l__delrocco_seq_temp_tl
\seq_if_empty:NTF \l__delrocco_seq_temp_seq
{
\tl_set:Nn \l__delrocco_seq_base_tl {#1}
\int_set:Nn \l__delrocco_seq_index_int { 0 }
}
{
% the last but one item is the number
\seq_pop_right:NN \l__delrocco_seq_temp_seq \l__delrocco_seq_temp_tl
% the base
\tl_set:Nx \l__delrocco_seq_base_tl { \seq_use:Nn \l__delrocco_seq_temp_seq {} }
% the index
\int_set:Nn \l__delrocco_seq_index_int { \l__delrocco_seq_temp_tl }
}
}

\ExplSyntaxOff

\begin{document}

$|\seq{a}{1..20}|$

$|\seq{a}{1..2n}[2,2,1]|$

$|\seq{a}{1..2n-1}[3,2,2]|$

$|\seq{a}{1..2n+1}[3,2,2]|$

$|\seq{a}{1..13}[3,2,2]|$

$\operatorname{Skip}(L)= \{ \seq{a}{1..2n-1}[2,1,2] \mid \seq{a}{1..2n}[3,2]\text{ is in } L \}$

$\operatorname{Skip}(L)= \{ \seq{a}{1..2n-1}[2,2,2] \mid \seq{a}{1..2n}[3,3]\text{ is in } L \}$

\end{document}


I didn't allow symbolic calculations for the starting point, but it could be added. No consistency check is done, as it would require quite a lot of algebra.

The space between items is twice \medmuskip, because an empty binary operation is set between any two items. This can be customized.

• Thank you! I modified @Manuel version so that it is used very similar to this. But this solution is technically 3 characters shorter to use, and some optional, optional arguments, which is cool. I wish I was as good as you guys as meta-programming :) – delrocco Feb 3 at 4:37