Smart-expansion of a range to a list of numbersDelete an element from a comma delimited listHow to use...
Is it expected that a reader will skip parts of what you write?
What is the meaning of the Russian idiom "to taste tuna" ("отведать тунца")?
I have a problematic assistant manager, but I can't fire him
How to make insert mode mapping count as multiple undos?
Is it possible to have 2 different but equal size real number sets that have the same mean and standard deviation?
Teaching a class likely meant to inflate the GPA of student athletes
How can I use String in enum for Apex?
Advantages of the Exponential Family: why should we study it and use it?
Has there been a multiethnic Star Trek character?
Which languages would be most useful in Europe at the end of the 19th century?
Next date with distinct digits
Smart-expansion of a range to a list of numbers
60s or 70s novel about Empire of Man making 1st contact with 1st discovered alien race
If there's something that implicates the president why is there then a national security issue? (John Dowd)
How creative should the DM let an artificer be in terms of what they can build?
Are polynomials with the same roots identical?
Can the removal of a duty-free sales trolley result in a measurable reduction in emissions?
Does putting salt first make it easier for attacker to bruteforce the hash?
Return a String containing only alphabets without spaces
A word that means "blending into a community too much"
Electricity free spaceship
How to “listen” to existing circuit
Why can my keyboard only digest 6 keypresses at a time?
Does the new finding on "reversing a quantum jump mid-flight" rule out any interpretations of QM?
Smart-expansion of a range to a list of numbers
Delete an element from a comma delimited listHow to use parameter numbers and foreachLaTeX3 versus pure LuaExpansion issue when adding to CSV list from within a foreachShuffle numbers in a loopSummation of a list of numbersDelimited def's and expansionIgnore expansion in edefError in foreach loop when number range defined with a macroHow to compare a string to a cs from a read properly?
I am wondering if there is a simple way to expand some input text such as "3-7" as "3,4,5,6,7"?
For context, I am using foreach
and want to be able to write
foreach x in {3-7, 9, 14, 52}
and have x
run through 3, 4, 5, 6, 7, 9, 14, and 52.
Alternatively, if there's an easy way to have
foreach x in {1,3,...7}
result in x
being defined as "1, 3, 4, 5, 6, and 7" instead of the standard "1, 3, 5, and 7", that would be great.
EDIT: I don't think I was clear in my explanation, but I personally understand how to do these foreach
commands in TeX, but wanted a simple input structure for a non-TeX user to use, i.e. typing makeProblems{1, 3-7, 9, 14, 52}
and having the associated problems as output.
foreach loops programming strings
add a comment |
I am wondering if there is a simple way to expand some input text such as "3-7" as "3,4,5,6,7"?
For context, I am using foreach
and want to be able to write
foreach x in {3-7, 9, 14, 52}
and have x
run through 3, 4, 5, 6, 7, 9, 14, and 52.
Alternatively, if there's an easy way to have
foreach x in {1,3,...7}
result in x
being defined as "1, 3, 4, 5, 6, and 7" instead of the standard "1, 3, 5, and 7", that would be great.
EDIT: I don't think I was clear in my explanation, but I personally understand how to do these foreach
commands in TeX, but wanted a simple input structure for a non-TeX user to use, i.e. typing makeProblems{1, 3-7, 9, 14, 52}
and having the associated problems as output.
foreach loops programming strings
Did you tryforeach x in {1,3,4,...,7}
?
– Phelype Oleinik
9 hours ago
I've thought about that, but wanted the input structure toforeach
to be as simple as possible to a non-TeX user. The user (not familiar with TeX), will call a commandmakeProblems{1, 3,...,7}
(where the input is thrown intoforeach
) and expect everything between 3 through 7 to output.
– ryanj1823
8 hours ago
foreach x in {3,...,7, 9, 14, 52}
andforeach x in {1,3,4,5,...,7}
?
– marmot
8 hours ago
To the first command: I understand that that works, but I wanted to avoid using the dots altogether if possible. To the second command: see my reply above to Pheylpe Oleinik
– ryanj1823
8 hours ago
add a comment |
I am wondering if there is a simple way to expand some input text such as "3-7" as "3,4,5,6,7"?
For context, I am using foreach
and want to be able to write
foreach x in {3-7, 9, 14, 52}
and have x
run through 3, 4, 5, 6, 7, 9, 14, and 52.
Alternatively, if there's an easy way to have
foreach x in {1,3,...7}
result in x
being defined as "1, 3, 4, 5, 6, and 7" instead of the standard "1, 3, 5, and 7", that would be great.
EDIT: I don't think I was clear in my explanation, but I personally understand how to do these foreach
commands in TeX, but wanted a simple input structure for a non-TeX user to use, i.e. typing makeProblems{1, 3-7, 9, 14, 52}
and having the associated problems as output.
foreach loops programming strings
I am wondering if there is a simple way to expand some input text such as "3-7" as "3,4,5,6,7"?
For context, I am using foreach
and want to be able to write
foreach x in {3-7, 9, 14, 52}
and have x
run through 3, 4, 5, 6, 7, 9, 14, and 52.
Alternatively, if there's an easy way to have
foreach x in {1,3,...7}
result in x
being defined as "1, 3, 4, 5, 6, and 7" instead of the standard "1, 3, 5, and 7", that would be great.
EDIT: I don't think I was clear in my explanation, but I personally understand how to do these foreach
commands in TeX, but wanted a simple input structure for a non-TeX user to use, i.e. typing makeProblems{1, 3-7, 9, 14, 52}
and having the associated problems as output.
foreach loops programming strings
foreach loops programming strings
edited 5 hours ago
Phelype Oleinik
29.4k64896
29.4k64896
asked 9 hours ago
ryanj1823ryanj1823
234
234
Did you tryforeach x in {1,3,4,...,7}
?
– Phelype Oleinik
9 hours ago
I've thought about that, but wanted the input structure toforeach
to be as simple as possible to a non-TeX user. The user (not familiar with TeX), will call a commandmakeProblems{1, 3,...,7}
(where the input is thrown intoforeach
) and expect everything between 3 through 7 to output.
– ryanj1823
8 hours ago
foreach x in {3,...,7, 9, 14, 52}
andforeach x in {1,3,4,5,...,7}
?
– marmot
8 hours ago
To the first command: I understand that that works, but I wanted to avoid using the dots altogether if possible. To the second command: see my reply above to Pheylpe Oleinik
– ryanj1823
8 hours ago
add a comment |
Did you tryforeach x in {1,3,4,...,7}
?
– Phelype Oleinik
9 hours ago
I've thought about that, but wanted the input structure toforeach
to be as simple as possible to a non-TeX user. The user (not familiar with TeX), will call a commandmakeProblems{1, 3,...,7}
(where the input is thrown intoforeach
) and expect everything between 3 through 7 to output.
– ryanj1823
8 hours ago
foreach x in {3,...,7, 9, 14, 52}
andforeach x in {1,3,4,5,...,7}
?
– marmot
8 hours ago
To the first command: I understand that that works, but I wanted to avoid using the dots altogether if possible. To the second command: see my reply above to Pheylpe Oleinik
– ryanj1823
8 hours ago
Did you try
foreach x in {1,3,4,...,7}
?– Phelype Oleinik
9 hours ago
Did you try
foreach x in {1,3,4,...,7}
?– Phelype Oleinik
9 hours ago
I've thought about that, but wanted the input structure to
foreach
to be as simple as possible to a non-TeX user. The user (not familiar with TeX), will call a command makeProblems{1, 3,...,7}
(where the input is thrown into foreach
) and expect everything between 3 through 7 to output.– ryanj1823
8 hours ago
I've thought about that, but wanted the input structure to
foreach
to be as simple as possible to a non-TeX user. The user (not familiar with TeX), will call a command makeProblems{1, 3,...,7}
(where the input is thrown into foreach
) and expect everything between 3 through 7 to output.– ryanj1823
8 hours ago
foreach x in {3,...,7, 9, 14, 52}
and foreach x in {1,3,4,5,...,7}
?– marmot
8 hours ago
foreach x in {3,...,7, 9, 14, 52}
and foreach x in {1,3,4,5,...,7}
?– marmot
8 hours ago
To the first command: I understand that that works, but I wanted to avoid using the dots altogether if possible. To the second command: see my reply above to Pheylpe Oleinik
– ryanj1823
8 hours ago
To the first command: I understand that that works, but I wanted to avoid using the dots altogether if possible. To the second command: see my reply above to Pheylpe Oleinik
– ryanj1823
8 hours ago
add a comment |
3 Answers
3
active
oldest
votes
With a little bit of code you can make yourself a parser. I defined makeProblems{<integer list>}{<code>}
for you, in which <integer list>
is a comma separated list of numbers where <x>-<y>
is parsed as the list of integers between <x>
and <y>
, inclusive. The function parses the list of numbers and then iterates over the generated list, and makes the current number available for <code>
as #1
. For example:
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
prints:
The code is long because, as the function takes user input, the function takes extra care to make sure that the <integer list>
doesn't contain wrong input.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
tl_new:N l_ryanj_list_tl
NewDocumentCommand makeProblems { m +m }
{
tl_clear:N l_ryanj_list_tl
exp_args:Nx clist_map_function:nN {#1} __ryanj_parse_item:n
tl_map_inline:Nn l_ryanj_list_tl {#2}
}
cs_new_protected:Npn __ryanj_add_item:n #1
{ tl_put_right:Nn l_ryanj_list_tl { {#1} } }
cs_new_protected:Npn __ryanj_parse_item:n #1
{
__ryanj_if_number:nTF {#1}
{ __ryanj_add_item:n {#1} }
{
str_if_in:nnTF {#1} {-}
{ exp_args:Nf __ryanj_parse_range:n { tl_to_str:n {#1} } }
{ msg_error:nnn { ryanj } { invalid-number } {#1} }
}
}
cs_new_protected:Npn __ryanj_parse_range:n #1
{ __ryanj_parse_range:nw {#1} #1 q_mark }
cs_new_protected:Npn __ryanj_parse_range:nw #1#2-#3 q_mark
{
__ryanj_validate_number:nn {#1} {#2}
__ryanj_validate_number:nn {#1} {#3}
int_step_function:nnnN {#2} { 1 } {#3} __ryanj_add_item:n
use_none:n q_stop
}
cs_new_protected:Npn __ryanj_validate_number:nn #1 #2
{
__ryanj_if_number:nF {#2}
{
msg_error:nnnn { ryanj } { invalid-number-in-range } {#2} {#1}
use_none_delimit_by_q_stop:w
}
}
msg_new:nnn { ryanj } { invalid-range } { Invalid~range~`#1'. }
msg_new:nnn { ryanj } { invalid-number } { Invalid~number~`#1'. }
msg_new:nnn { ryanj } { invalid-number-in-range } { Invalid~number~`#1'~in~range~`#2'. }
prg_new_conditional:Npnn __ryanj_if_number:n #1 { T, F, TF }
{
tl_if_empty:oTF
{ tex_romannumeral:D - 0#1 exp_stop_f: }
{
tl_if_empty:nTF {#1}
{ prg_return_false: }
{ prg_return_true: }
}
{ prg_return_false: }
}
% For older expl3:
prg_set_protected_conditional:Npnn str_if_in:nn #1#2 { T , F , TF }
{
use:x
{ tl_if_in:nnTF { tl_to_str:n {#1} } { tl_to_str:n {#2} } }
{ prg_return_true: } { prg_return_false: }
}
ExplSyntaxOff
begin{document}
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
end{document}
This looks great! Although copying and pasting this produces the errorsUndefined control sequence ...3-7, 9, 14, 52}{Do something with #1.par}
andInvalid number `3-7' ...3-7, 9, 14, 52}{Do something with #1.par}
... any edits maybe? Thanks again!
– ryanj1823
6 hours ago
@ryanj1823 You probably have some older version of thel3kernel
. Could you upload the.log
file somewhere for me to check? (pastebin.com, for example.)
– Phelype Oleinik
6 hours ago
pastebin.com/1euZ6R4n ...that should work, much appreciated
– ryanj1823
6 hours ago
@ryanj1823 Try it now. There were twoexpl3
functions which don't exist in your distribution (TeXLive 2017), so I adapted the code. (I can't test, though, so tell me if it doesn't work.)
– Phelype Oleinik
6 hours ago
1
@ryanj1823 Done. Now the command expands its argument before processing. Of course you can alwaysexpandaftermakeProblemsexpandafter{DesiredProblems}
, but I think that's not exactly user-friendly.
– Phelype Oleinik
6 hours ago
|
show 2 more comments
documentclass{article}
usepackage{listofitems,pgffor}
newcommandmakeProblems[2]{%
setsepchar{,/-}%
readlist*numlist{#1}%
defz##1{#2par}%
foreachitemzzinnumlist[]{%
ifnumlistlennumlist[zzcnt]=1relaxz{zz}else
itemtomacronumlist[zzcnt,1]tmpA
itemtomacronumlist[zzcnt,2]tmpB
foreachzzz in {tmpA,...,tmpB}{%
z{zzz}}%
fi
}%
}
begin{document}
makeProblems{1,3-7, 9, 14-16, 52}{Do something with #1.}
end{document}
This works great too! Thanks!
– ryanj1823
6 hours ago
add a comment |
I map the given comma separated list; each item is examined and if it contains a hyphen, a loop is done; in any case, an integer is added to a sequence.
Finally the sequence is expanded with separators between the items; optionally this token list is saved to a macro.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{expandlist}{om}
{
ryanj_expandlist:n { #2 }
IfNoValueTF { #1 }
{
ryanj_expandlist_print:
}
{
ryanj_expandlist_store:N #1
}
}
tl_new:N l_ryan_expandlist_tl
seq_new:N l__ryan_expandlist_seq
cs_new_protected:Nn ryanj_expandlist:n
{
seq_clear:N l__ryan_expandlist_seq
clist_map_function:nN { #1 } __ryan_expandlist_item:n
tl_set:Nx l_ryan_expandlist_tl
{
seq_use:Nnnn l__ryan_expandlist_seq {~and~} { ,~ } { ,~and~ }
}
}
cs_new_protected:Nn __ryan_expandlist_item:n
{
__ryan_expandlist_item:w #1 - - q_stop
}
cs_new_protected:Npn __ryan_expandlist_item:w #1 - #2 - #3 q_stop
{
tl_if_blank:nTF { #2 }
{
seq_put_right:Nn l__ryan_expandlist_seq { #1 }
}
{
int_step_inline:nnn { #1 } { #2 } { seq_put_right:Nn l__ryan_expandlist_seq { ##1 } }
}
}
cs_new:Nn ryanj_expandlist_print:
{
tl_use:N l_ryan_expandlist_tl
}
cs_new_protected:Nn ryanj_expandlist_store:N
{
tl_if_exist:NF #1
{
tl_set_eq:NN #1 l_ryan_expandlist_tl
}
}
ExplSyntaxOff
begin{document}
expandlist{3-7, 9, 14, 52}
expandlist{1}
expandlist{1,4}
expandlist{1-2}
expandlist[foo]{3-7, 9, 14, 52}
texttt{meaningfoo}
end{document}
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f494712%2fsmart-expansion-of-a-range-to-a-list-of-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
With a little bit of code you can make yourself a parser. I defined makeProblems{<integer list>}{<code>}
for you, in which <integer list>
is a comma separated list of numbers where <x>-<y>
is parsed as the list of integers between <x>
and <y>
, inclusive. The function parses the list of numbers and then iterates over the generated list, and makes the current number available for <code>
as #1
. For example:
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
prints:
The code is long because, as the function takes user input, the function takes extra care to make sure that the <integer list>
doesn't contain wrong input.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
tl_new:N l_ryanj_list_tl
NewDocumentCommand makeProblems { m +m }
{
tl_clear:N l_ryanj_list_tl
exp_args:Nx clist_map_function:nN {#1} __ryanj_parse_item:n
tl_map_inline:Nn l_ryanj_list_tl {#2}
}
cs_new_protected:Npn __ryanj_add_item:n #1
{ tl_put_right:Nn l_ryanj_list_tl { {#1} } }
cs_new_protected:Npn __ryanj_parse_item:n #1
{
__ryanj_if_number:nTF {#1}
{ __ryanj_add_item:n {#1} }
{
str_if_in:nnTF {#1} {-}
{ exp_args:Nf __ryanj_parse_range:n { tl_to_str:n {#1} } }
{ msg_error:nnn { ryanj } { invalid-number } {#1} }
}
}
cs_new_protected:Npn __ryanj_parse_range:n #1
{ __ryanj_parse_range:nw {#1} #1 q_mark }
cs_new_protected:Npn __ryanj_parse_range:nw #1#2-#3 q_mark
{
__ryanj_validate_number:nn {#1} {#2}
__ryanj_validate_number:nn {#1} {#3}
int_step_function:nnnN {#2} { 1 } {#3} __ryanj_add_item:n
use_none:n q_stop
}
cs_new_protected:Npn __ryanj_validate_number:nn #1 #2
{
__ryanj_if_number:nF {#2}
{
msg_error:nnnn { ryanj } { invalid-number-in-range } {#2} {#1}
use_none_delimit_by_q_stop:w
}
}
msg_new:nnn { ryanj } { invalid-range } { Invalid~range~`#1'. }
msg_new:nnn { ryanj } { invalid-number } { Invalid~number~`#1'. }
msg_new:nnn { ryanj } { invalid-number-in-range } { Invalid~number~`#1'~in~range~`#2'. }
prg_new_conditional:Npnn __ryanj_if_number:n #1 { T, F, TF }
{
tl_if_empty:oTF
{ tex_romannumeral:D - 0#1 exp_stop_f: }
{
tl_if_empty:nTF {#1}
{ prg_return_false: }
{ prg_return_true: }
}
{ prg_return_false: }
}
% For older expl3:
prg_set_protected_conditional:Npnn str_if_in:nn #1#2 { T , F , TF }
{
use:x
{ tl_if_in:nnTF { tl_to_str:n {#1} } { tl_to_str:n {#2} } }
{ prg_return_true: } { prg_return_false: }
}
ExplSyntaxOff
begin{document}
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
end{document}
This looks great! Although copying and pasting this produces the errorsUndefined control sequence ...3-7, 9, 14, 52}{Do something with #1.par}
andInvalid number `3-7' ...3-7, 9, 14, 52}{Do something with #1.par}
... any edits maybe? Thanks again!
– ryanj1823
6 hours ago
@ryanj1823 You probably have some older version of thel3kernel
. Could you upload the.log
file somewhere for me to check? (pastebin.com, for example.)
– Phelype Oleinik
6 hours ago
pastebin.com/1euZ6R4n ...that should work, much appreciated
– ryanj1823
6 hours ago
@ryanj1823 Try it now. There were twoexpl3
functions which don't exist in your distribution (TeXLive 2017), so I adapted the code. (I can't test, though, so tell me if it doesn't work.)
– Phelype Oleinik
6 hours ago
1
@ryanj1823 Done. Now the command expands its argument before processing. Of course you can alwaysexpandaftermakeProblemsexpandafter{DesiredProblems}
, but I think that's not exactly user-friendly.
– Phelype Oleinik
6 hours ago
|
show 2 more comments
With a little bit of code you can make yourself a parser. I defined makeProblems{<integer list>}{<code>}
for you, in which <integer list>
is a comma separated list of numbers where <x>-<y>
is parsed as the list of integers between <x>
and <y>
, inclusive. The function parses the list of numbers and then iterates over the generated list, and makes the current number available for <code>
as #1
. For example:
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
prints:
The code is long because, as the function takes user input, the function takes extra care to make sure that the <integer list>
doesn't contain wrong input.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
tl_new:N l_ryanj_list_tl
NewDocumentCommand makeProblems { m +m }
{
tl_clear:N l_ryanj_list_tl
exp_args:Nx clist_map_function:nN {#1} __ryanj_parse_item:n
tl_map_inline:Nn l_ryanj_list_tl {#2}
}
cs_new_protected:Npn __ryanj_add_item:n #1
{ tl_put_right:Nn l_ryanj_list_tl { {#1} } }
cs_new_protected:Npn __ryanj_parse_item:n #1
{
__ryanj_if_number:nTF {#1}
{ __ryanj_add_item:n {#1} }
{
str_if_in:nnTF {#1} {-}
{ exp_args:Nf __ryanj_parse_range:n { tl_to_str:n {#1} } }
{ msg_error:nnn { ryanj } { invalid-number } {#1} }
}
}
cs_new_protected:Npn __ryanj_parse_range:n #1
{ __ryanj_parse_range:nw {#1} #1 q_mark }
cs_new_protected:Npn __ryanj_parse_range:nw #1#2-#3 q_mark
{
__ryanj_validate_number:nn {#1} {#2}
__ryanj_validate_number:nn {#1} {#3}
int_step_function:nnnN {#2} { 1 } {#3} __ryanj_add_item:n
use_none:n q_stop
}
cs_new_protected:Npn __ryanj_validate_number:nn #1 #2
{
__ryanj_if_number:nF {#2}
{
msg_error:nnnn { ryanj } { invalid-number-in-range } {#2} {#1}
use_none_delimit_by_q_stop:w
}
}
msg_new:nnn { ryanj } { invalid-range } { Invalid~range~`#1'. }
msg_new:nnn { ryanj } { invalid-number } { Invalid~number~`#1'. }
msg_new:nnn { ryanj } { invalid-number-in-range } { Invalid~number~`#1'~in~range~`#2'. }
prg_new_conditional:Npnn __ryanj_if_number:n #1 { T, F, TF }
{
tl_if_empty:oTF
{ tex_romannumeral:D - 0#1 exp_stop_f: }
{
tl_if_empty:nTF {#1}
{ prg_return_false: }
{ prg_return_true: }
}
{ prg_return_false: }
}
% For older expl3:
prg_set_protected_conditional:Npnn str_if_in:nn #1#2 { T , F , TF }
{
use:x
{ tl_if_in:nnTF { tl_to_str:n {#1} } { tl_to_str:n {#2} } }
{ prg_return_true: } { prg_return_false: }
}
ExplSyntaxOff
begin{document}
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
end{document}
This looks great! Although copying and pasting this produces the errorsUndefined control sequence ...3-7, 9, 14, 52}{Do something with #1.par}
andInvalid number `3-7' ...3-7, 9, 14, 52}{Do something with #1.par}
... any edits maybe? Thanks again!
– ryanj1823
6 hours ago
@ryanj1823 You probably have some older version of thel3kernel
. Could you upload the.log
file somewhere for me to check? (pastebin.com, for example.)
– Phelype Oleinik
6 hours ago
pastebin.com/1euZ6R4n ...that should work, much appreciated
– ryanj1823
6 hours ago
@ryanj1823 Try it now. There were twoexpl3
functions which don't exist in your distribution (TeXLive 2017), so I adapted the code. (I can't test, though, so tell me if it doesn't work.)
– Phelype Oleinik
6 hours ago
1
@ryanj1823 Done. Now the command expands its argument before processing. Of course you can alwaysexpandaftermakeProblemsexpandafter{DesiredProblems}
, but I think that's not exactly user-friendly.
– Phelype Oleinik
6 hours ago
|
show 2 more comments
With a little bit of code you can make yourself a parser. I defined makeProblems{<integer list>}{<code>}
for you, in which <integer list>
is a comma separated list of numbers where <x>-<y>
is parsed as the list of integers between <x>
and <y>
, inclusive. The function parses the list of numbers and then iterates over the generated list, and makes the current number available for <code>
as #1
. For example:
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
prints:
The code is long because, as the function takes user input, the function takes extra care to make sure that the <integer list>
doesn't contain wrong input.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
tl_new:N l_ryanj_list_tl
NewDocumentCommand makeProblems { m +m }
{
tl_clear:N l_ryanj_list_tl
exp_args:Nx clist_map_function:nN {#1} __ryanj_parse_item:n
tl_map_inline:Nn l_ryanj_list_tl {#2}
}
cs_new_protected:Npn __ryanj_add_item:n #1
{ tl_put_right:Nn l_ryanj_list_tl { {#1} } }
cs_new_protected:Npn __ryanj_parse_item:n #1
{
__ryanj_if_number:nTF {#1}
{ __ryanj_add_item:n {#1} }
{
str_if_in:nnTF {#1} {-}
{ exp_args:Nf __ryanj_parse_range:n { tl_to_str:n {#1} } }
{ msg_error:nnn { ryanj } { invalid-number } {#1} }
}
}
cs_new_protected:Npn __ryanj_parse_range:n #1
{ __ryanj_parse_range:nw {#1} #1 q_mark }
cs_new_protected:Npn __ryanj_parse_range:nw #1#2-#3 q_mark
{
__ryanj_validate_number:nn {#1} {#2}
__ryanj_validate_number:nn {#1} {#3}
int_step_function:nnnN {#2} { 1 } {#3} __ryanj_add_item:n
use_none:n q_stop
}
cs_new_protected:Npn __ryanj_validate_number:nn #1 #2
{
__ryanj_if_number:nF {#2}
{
msg_error:nnnn { ryanj } { invalid-number-in-range } {#2} {#1}
use_none_delimit_by_q_stop:w
}
}
msg_new:nnn { ryanj } { invalid-range } { Invalid~range~`#1'. }
msg_new:nnn { ryanj } { invalid-number } { Invalid~number~`#1'. }
msg_new:nnn { ryanj } { invalid-number-in-range } { Invalid~number~`#1'~in~range~`#2'. }
prg_new_conditional:Npnn __ryanj_if_number:n #1 { T, F, TF }
{
tl_if_empty:oTF
{ tex_romannumeral:D - 0#1 exp_stop_f: }
{
tl_if_empty:nTF {#1}
{ prg_return_false: }
{ prg_return_true: }
}
{ prg_return_false: }
}
% For older expl3:
prg_set_protected_conditional:Npnn str_if_in:nn #1#2 { T , F , TF }
{
use:x
{ tl_if_in:nnTF { tl_to_str:n {#1} } { tl_to_str:n {#2} } }
{ prg_return_true: } { prg_return_false: }
}
ExplSyntaxOff
begin{document}
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
end{document}
With a little bit of code you can make yourself a parser. I defined makeProblems{<integer list>}{<code>}
for you, in which <integer list>
is a comma separated list of numbers where <x>-<y>
is parsed as the list of integers between <x>
and <y>
, inclusive. The function parses the list of numbers and then iterates over the generated list, and makes the current number available for <code>
as #1
. For example:
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
prints:
The code is long because, as the function takes user input, the function takes extra care to make sure that the <integer list>
doesn't contain wrong input.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
tl_new:N l_ryanj_list_tl
NewDocumentCommand makeProblems { m +m }
{
tl_clear:N l_ryanj_list_tl
exp_args:Nx clist_map_function:nN {#1} __ryanj_parse_item:n
tl_map_inline:Nn l_ryanj_list_tl {#2}
}
cs_new_protected:Npn __ryanj_add_item:n #1
{ tl_put_right:Nn l_ryanj_list_tl { {#1} } }
cs_new_protected:Npn __ryanj_parse_item:n #1
{
__ryanj_if_number:nTF {#1}
{ __ryanj_add_item:n {#1} }
{
str_if_in:nnTF {#1} {-}
{ exp_args:Nf __ryanj_parse_range:n { tl_to_str:n {#1} } }
{ msg_error:nnn { ryanj } { invalid-number } {#1} }
}
}
cs_new_protected:Npn __ryanj_parse_range:n #1
{ __ryanj_parse_range:nw {#1} #1 q_mark }
cs_new_protected:Npn __ryanj_parse_range:nw #1#2-#3 q_mark
{
__ryanj_validate_number:nn {#1} {#2}
__ryanj_validate_number:nn {#1} {#3}
int_step_function:nnnN {#2} { 1 } {#3} __ryanj_add_item:n
use_none:n q_stop
}
cs_new_protected:Npn __ryanj_validate_number:nn #1 #2
{
__ryanj_if_number:nF {#2}
{
msg_error:nnnn { ryanj } { invalid-number-in-range } {#2} {#1}
use_none_delimit_by_q_stop:w
}
}
msg_new:nnn { ryanj } { invalid-range } { Invalid~range~`#1'. }
msg_new:nnn { ryanj } { invalid-number } { Invalid~number~`#1'. }
msg_new:nnn { ryanj } { invalid-number-in-range } { Invalid~number~`#1'~in~range~`#2'. }
prg_new_conditional:Npnn __ryanj_if_number:n #1 { T, F, TF }
{
tl_if_empty:oTF
{ tex_romannumeral:D - 0#1 exp_stop_f: }
{
tl_if_empty:nTF {#1}
{ prg_return_false: }
{ prg_return_true: }
}
{ prg_return_false: }
}
% For older expl3:
prg_set_protected_conditional:Npnn str_if_in:nn #1#2 { T , F , TF }
{
use:x
{ tl_if_in:nnTF { tl_to_str:n {#1} } { tl_to_str:n {#2} } }
{ prg_return_true: } { prg_return_false: }
}
ExplSyntaxOff
begin{document}
makeProblems{1,3-7, 9, 14, 52}{Do something with #1.par}
end{document}
edited 6 hours ago
answered 8 hours ago
Phelype OleinikPhelype Oleinik
29.4k64896
29.4k64896
This looks great! Although copying and pasting this produces the errorsUndefined control sequence ...3-7, 9, 14, 52}{Do something with #1.par}
andInvalid number `3-7' ...3-7, 9, 14, 52}{Do something with #1.par}
... any edits maybe? Thanks again!
– ryanj1823
6 hours ago
@ryanj1823 You probably have some older version of thel3kernel
. Could you upload the.log
file somewhere for me to check? (pastebin.com, for example.)
– Phelype Oleinik
6 hours ago
pastebin.com/1euZ6R4n ...that should work, much appreciated
– ryanj1823
6 hours ago
@ryanj1823 Try it now. There were twoexpl3
functions which don't exist in your distribution (TeXLive 2017), so I adapted the code. (I can't test, though, so tell me if it doesn't work.)
– Phelype Oleinik
6 hours ago
1
@ryanj1823 Done. Now the command expands its argument before processing. Of course you can alwaysexpandaftermakeProblemsexpandafter{DesiredProblems}
, but I think that's not exactly user-friendly.
– Phelype Oleinik
6 hours ago
|
show 2 more comments
This looks great! Although copying and pasting this produces the errorsUndefined control sequence ...3-7, 9, 14, 52}{Do something with #1.par}
andInvalid number `3-7' ...3-7, 9, 14, 52}{Do something with #1.par}
... any edits maybe? Thanks again!
– ryanj1823
6 hours ago
@ryanj1823 You probably have some older version of thel3kernel
. Could you upload the.log
file somewhere for me to check? (pastebin.com, for example.)
– Phelype Oleinik
6 hours ago
pastebin.com/1euZ6R4n ...that should work, much appreciated
– ryanj1823
6 hours ago
@ryanj1823 Try it now. There were twoexpl3
functions which don't exist in your distribution (TeXLive 2017), so I adapted the code. (I can't test, though, so tell me if it doesn't work.)
– Phelype Oleinik
6 hours ago
1
@ryanj1823 Done. Now the command expands its argument before processing. Of course you can alwaysexpandaftermakeProblemsexpandafter{DesiredProblems}
, but I think that's not exactly user-friendly.
– Phelype Oleinik
6 hours ago
This looks great! Although copying and pasting this produces the errors
Undefined control sequence ...3-7, 9, 14, 52}{Do something with #1.par}
and Invalid number `3-7' ...3-7, 9, 14, 52}{Do something with #1.par}
... any edits maybe? Thanks again!– ryanj1823
6 hours ago
This looks great! Although copying and pasting this produces the errors
Undefined control sequence ...3-7, 9, 14, 52}{Do something with #1.par}
and Invalid number `3-7' ...3-7, 9, 14, 52}{Do something with #1.par}
... any edits maybe? Thanks again!– ryanj1823
6 hours ago
@ryanj1823 You probably have some older version of the
l3kernel
. Could you upload the .log
file somewhere for me to check? (pastebin.com, for example.)– Phelype Oleinik
6 hours ago
@ryanj1823 You probably have some older version of the
l3kernel
. Could you upload the .log
file somewhere for me to check? (pastebin.com, for example.)– Phelype Oleinik
6 hours ago
pastebin.com/1euZ6R4n ...that should work, much appreciated
– ryanj1823
6 hours ago
pastebin.com/1euZ6R4n ...that should work, much appreciated
– ryanj1823
6 hours ago
@ryanj1823 Try it now. There were two
expl3
functions which don't exist in your distribution (TeXLive 2017), so I adapted the code. (I can't test, though, so tell me if it doesn't work.)– Phelype Oleinik
6 hours ago
@ryanj1823 Try it now. There were two
expl3
functions which don't exist in your distribution (TeXLive 2017), so I adapted the code. (I can't test, though, so tell me if it doesn't work.)– Phelype Oleinik
6 hours ago
1
1
@ryanj1823 Done. Now the command expands its argument before processing. Of course you can always
expandaftermakeProblemsexpandafter{DesiredProblems}
, but I think that's not exactly user-friendly.– Phelype Oleinik
6 hours ago
@ryanj1823 Done. Now the command expands its argument before processing. Of course you can always
expandaftermakeProblemsexpandafter{DesiredProblems}
, but I think that's not exactly user-friendly.– Phelype Oleinik
6 hours ago
|
show 2 more comments
documentclass{article}
usepackage{listofitems,pgffor}
newcommandmakeProblems[2]{%
setsepchar{,/-}%
readlist*numlist{#1}%
defz##1{#2par}%
foreachitemzzinnumlist[]{%
ifnumlistlennumlist[zzcnt]=1relaxz{zz}else
itemtomacronumlist[zzcnt,1]tmpA
itemtomacronumlist[zzcnt,2]tmpB
foreachzzz in {tmpA,...,tmpB}{%
z{zzz}}%
fi
}%
}
begin{document}
makeProblems{1,3-7, 9, 14-16, 52}{Do something with #1.}
end{document}
This works great too! Thanks!
– ryanj1823
6 hours ago
add a comment |
documentclass{article}
usepackage{listofitems,pgffor}
newcommandmakeProblems[2]{%
setsepchar{,/-}%
readlist*numlist{#1}%
defz##1{#2par}%
foreachitemzzinnumlist[]{%
ifnumlistlennumlist[zzcnt]=1relaxz{zz}else
itemtomacronumlist[zzcnt,1]tmpA
itemtomacronumlist[zzcnt,2]tmpB
foreachzzz in {tmpA,...,tmpB}{%
z{zzz}}%
fi
}%
}
begin{document}
makeProblems{1,3-7, 9, 14-16, 52}{Do something with #1.}
end{document}
This works great too! Thanks!
– ryanj1823
6 hours ago
add a comment |
documentclass{article}
usepackage{listofitems,pgffor}
newcommandmakeProblems[2]{%
setsepchar{,/-}%
readlist*numlist{#1}%
defz##1{#2par}%
foreachitemzzinnumlist[]{%
ifnumlistlennumlist[zzcnt]=1relaxz{zz}else
itemtomacronumlist[zzcnt,1]tmpA
itemtomacronumlist[zzcnt,2]tmpB
foreachzzz in {tmpA,...,tmpB}{%
z{zzz}}%
fi
}%
}
begin{document}
makeProblems{1,3-7, 9, 14-16, 52}{Do something with #1.}
end{document}
documentclass{article}
usepackage{listofitems,pgffor}
newcommandmakeProblems[2]{%
setsepchar{,/-}%
readlist*numlist{#1}%
defz##1{#2par}%
foreachitemzzinnumlist[]{%
ifnumlistlennumlist[zzcnt]=1relaxz{zz}else
itemtomacronumlist[zzcnt,1]tmpA
itemtomacronumlist[zzcnt,2]tmpB
foreachzzz in {tmpA,...,tmpB}{%
z{zzz}}%
fi
}%
}
begin{document}
makeProblems{1,3-7, 9, 14-16, 52}{Do something with #1.}
end{document}
answered 6 hours ago
Steven B. SegletesSteven B. Segletes
166k9210427
166k9210427
This works great too! Thanks!
– ryanj1823
6 hours ago
add a comment |
This works great too! Thanks!
– ryanj1823
6 hours ago
This works great too! Thanks!
– ryanj1823
6 hours ago
This works great too! Thanks!
– ryanj1823
6 hours ago
add a comment |
I map the given comma separated list; each item is examined and if it contains a hyphen, a loop is done; in any case, an integer is added to a sequence.
Finally the sequence is expanded with separators between the items; optionally this token list is saved to a macro.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{expandlist}{om}
{
ryanj_expandlist:n { #2 }
IfNoValueTF { #1 }
{
ryanj_expandlist_print:
}
{
ryanj_expandlist_store:N #1
}
}
tl_new:N l_ryan_expandlist_tl
seq_new:N l__ryan_expandlist_seq
cs_new_protected:Nn ryanj_expandlist:n
{
seq_clear:N l__ryan_expandlist_seq
clist_map_function:nN { #1 } __ryan_expandlist_item:n
tl_set:Nx l_ryan_expandlist_tl
{
seq_use:Nnnn l__ryan_expandlist_seq {~and~} { ,~ } { ,~and~ }
}
}
cs_new_protected:Nn __ryan_expandlist_item:n
{
__ryan_expandlist_item:w #1 - - q_stop
}
cs_new_protected:Npn __ryan_expandlist_item:w #1 - #2 - #3 q_stop
{
tl_if_blank:nTF { #2 }
{
seq_put_right:Nn l__ryan_expandlist_seq { #1 }
}
{
int_step_inline:nnn { #1 } { #2 } { seq_put_right:Nn l__ryan_expandlist_seq { ##1 } }
}
}
cs_new:Nn ryanj_expandlist_print:
{
tl_use:N l_ryan_expandlist_tl
}
cs_new_protected:Nn ryanj_expandlist_store:N
{
tl_if_exist:NF #1
{
tl_set_eq:NN #1 l_ryan_expandlist_tl
}
}
ExplSyntaxOff
begin{document}
expandlist{3-7, 9, 14, 52}
expandlist{1}
expandlist{1,4}
expandlist{1-2}
expandlist[foo]{3-7, 9, 14, 52}
texttt{meaningfoo}
end{document}
add a comment |
I map the given comma separated list; each item is examined and if it contains a hyphen, a loop is done; in any case, an integer is added to a sequence.
Finally the sequence is expanded with separators between the items; optionally this token list is saved to a macro.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{expandlist}{om}
{
ryanj_expandlist:n { #2 }
IfNoValueTF { #1 }
{
ryanj_expandlist_print:
}
{
ryanj_expandlist_store:N #1
}
}
tl_new:N l_ryan_expandlist_tl
seq_new:N l__ryan_expandlist_seq
cs_new_protected:Nn ryanj_expandlist:n
{
seq_clear:N l__ryan_expandlist_seq
clist_map_function:nN { #1 } __ryan_expandlist_item:n
tl_set:Nx l_ryan_expandlist_tl
{
seq_use:Nnnn l__ryan_expandlist_seq {~and~} { ,~ } { ,~and~ }
}
}
cs_new_protected:Nn __ryan_expandlist_item:n
{
__ryan_expandlist_item:w #1 - - q_stop
}
cs_new_protected:Npn __ryan_expandlist_item:w #1 - #2 - #3 q_stop
{
tl_if_blank:nTF { #2 }
{
seq_put_right:Nn l__ryan_expandlist_seq { #1 }
}
{
int_step_inline:nnn { #1 } { #2 } { seq_put_right:Nn l__ryan_expandlist_seq { ##1 } }
}
}
cs_new:Nn ryanj_expandlist_print:
{
tl_use:N l_ryan_expandlist_tl
}
cs_new_protected:Nn ryanj_expandlist_store:N
{
tl_if_exist:NF #1
{
tl_set_eq:NN #1 l_ryan_expandlist_tl
}
}
ExplSyntaxOff
begin{document}
expandlist{3-7, 9, 14, 52}
expandlist{1}
expandlist{1,4}
expandlist{1-2}
expandlist[foo]{3-7, 9, 14, 52}
texttt{meaningfoo}
end{document}
add a comment |
I map the given comma separated list; each item is examined and if it contains a hyphen, a loop is done; in any case, an integer is added to a sequence.
Finally the sequence is expanded with separators between the items; optionally this token list is saved to a macro.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{expandlist}{om}
{
ryanj_expandlist:n { #2 }
IfNoValueTF { #1 }
{
ryanj_expandlist_print:
}
{
ryanj_expandlist_store:N #1
}
}
tl_new:N l_ryan_expandlist_tl
seq_new:N l__ryan_expandlist_seq
cs_new_protected:Nn ryanj_expandlist:n
{
seq_clear:N l__ryan_expandlist_seq
clist_map_function:nN { #1 } __ryan_expandlist_item:n
tl_set:Nx l_ryan_expandlist_tl
{
seq_use:Nnnn l__ryan_expandlist_seq {~and~} { ,~ } { ,~and~ }
}
}
cs_new_protected:Nn __ryan_expandlist_item:n
{
__ryan_expandlist_item:w #1 - - q_stop
}
cs_new_protected:Npn __ryan_expandlist_item:w #1 - #2 - #3 q_stop
{
tl_if_blank:nTF { #2 }
{
seq_put_right:Nn l__ryan_expandlist_seq { #1 }
}
{
int_step_inline:nnn { #1 } { #2 } { seq_put_right:Nn l__ryan_expandlist_seq { ##1 } }
}
}
cs_new:Nn ryanj_expandlist_print:
{
tl_use:N l_ryan_expandlist_tl
}
cs_new_protected:Nn ryanj_expandlist_store:N
{
tl_if_exist:NF #1
{
tl_set_eq:NN #1 l_ryan_expandlist_tl
}
}
ExplSyntaxOff
begin{document}
expandlist{3-7, 9, 14, 52}
expandlist{1}
expandlist{1,4}
expandlist{1-2}
expandlist[foo]{3-7, 9, 14, 52}
texttt{meaningfoo}
end{document}
I map the given comma separated list; each item is examined and if it contains a hyphen, a loop is done; in any case, an integer is added to a sequence.
Finally the sequence is expanded with separators between the items; optionally this token list is saved to a macro.
documentclass{article}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{expandlist}{om}
{
ryanj_expandlist:n { #2 }
IfNoValueTF { #1 }
{
ryanj_expandlist_print:
}
{
ryanj_expandlist_store:N #1
}
}
tl_new:N l_ryan_expandlist_tl
seq_new:N l__ryan_expandlist_seq
cs_new_protected:Nn ryanj_expandlist:n
{
seq_clear:N l__ryan_expandlist_seq
clist_map_function:nN { #1 } __ryan_expandlist_item:n
tl_set:Nx l_ryan_expandlist_tl
{
seq_use:Nnnn l__ryan_expandlist_seq {~and~} { ,~ } { ,~and~ }
}
}
cs_new_protected:Nn __ryan_expandlist_item:n
{
__ryan_expandlist_item:w #1 - - q_stop
}
cs_new_protected:Npn __ryan_expandlist_item:w #1 - #2 - #3 q_stop
{
tl_if_blank:nTF { #2 }
{
seq_put_right:Nn l__ryan_expandlist_seq { #1 }
}
{
int_step_inline:nnn { #1 } { #2 } { seq_put_right:Nn l__ryan_expandlist_seq { ##1 } }
}
}
cs_new:Nn ryanj_expandlist_print:
{
tl_use:N l_ryan_expandlist_tl
}
cs_new_protected:Nn ryanj_expandlist_store:N
{
tl_if_exist:NF #1
{
tl_set_eq:NN #1 l_ryan_expandlist_tl
}
}
ExplSyntaxOff
begin{document}
expandlist{3-7, 9, 14, 52}
expandlist{1}
expandlist{1,4}
expandlist{1-2}
expandlist[foo]{3-7, 9, 14, 52}
texttt{meaningfoo}
end{document}
answered 5 hours ago
egregegreg
747k8919543295
747k8919543295
add a comment |
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f494712%2fsmart-expansion-of-a-range-to-a-list-of-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Did you try
foreach x in {1,3,4,...,7}
?– Phelype Oleinik
9 hours ago
I've thought about that, but wanted the input structure to
foreach
to be as simple as possible to a non-TeX user. The user (not familiar with TeX), will call a commandmakeProblems{1, 3,...,7}
(where the input is thrown intoforeach
) and expect everything between 3 through 7 to output.– ryanj1823
8 hours ago
foreach x in {3,...,7, 9, 14, 52}
andforeach x in {1,3,4,5,...,7}
?– marmot
8 hours ago
To the first command: I understand that that works, but I wanted to avoid using the dots altogether if possible. To the second command: see my reply above to Pheylpe Oleinik
– ryanj1823
8 hours ago