TeX - LaTeX Asked on May 28, 2021
Consider the following:
documentclass{article}
usepackage{expl3}
ExplSyntaxOn
cs_new_eq:NN calc fp_eval:n
ExplSyntaxOff
defvalueA{7}
defvalueB{19}
defvalueC{41}
defvalueD{31}
defvalueE{25}
defvalueF{17}
defvalueG{7}
defvalueH{3}
begin{document}
noindent I have the list
[
valueA,valueB,valueC,valueD,valueE,valueF,valueG,valueH
]
in which the largest element is $calc{max(valueA,valueB,valueC,valueD,valueE,valueF,valueG,valueH)}$ (but that is of no importance to me).[baselineskip]
How can I get LaTeX{} to extract the position number of the largest element in a list? (In the example above, the answer is of course `$3$'.)
end{document}
Note
It doesn’t have to be a LaTeX 3 solution, but I need to compile the original document (i.e., the one I need the solution for) via latex
–> dvips
–> ps2pdf
.
Also, the list is generated via the def
method.
Just using expl3
we can do this using one loop or two. A one loop version needs to work out the maximum value and track the position at the same time:
documentclass{article}
usepackage{expl3,xparse}
ExplSyntaxOn
NewDocumentCommand maxposition { m }
{
svend_clist_pos_max:n {#1}
}
cs_new:Npn svend_clist_pos_max:n #1
{
__svend_clist_pos_max:nnnw c_zero c_zero { -c_max_int }
#1 , q_recursion_tail , q_recursion_stop
}
cs_new:Npn __svend_clist_pos_max:nnnw #1#2#3#4 ,
{
quark_if_recursion_tail_stop_do:nn {#4} {#1}
fp_compare:nNnTF {#4} > {#3}
{
__svend_clist_pos_max:fnnw
{ int_eval:n { #1 + #2 + c_one } } c_zero {#4}
}
{
__svend_clist_pos_max:nfnw
{#1} { int_eval:n { #2 + c_one } } {#3}
}
}
cs_generate_variant:Nn __svend_clist_pos_max:nnnw { f , nf }
ExplSyntaxOff
defvalueA{7}
defvalueB{19}
defvalueC{41}
defvalueD{31}
defvalueE{25}
defvalueF{17}
defvalueG{7}
defvalueH{3}
begin{document}
maxposition{valueA,valueB,valueC,valueD,valueE,valueF,valueG,valueH}
end{document}
whereas a two loop version first finds the maximum then the position so there are fewer things to track in one go
documentclass{article}
usepackage{expl3,xparse}
ExplSyntaxOn
NewDocumentCommand maxposition { m }
{
svend_clist_pos_max:n {#1}
}
cs_new:Npn svend_clist_pos_max:n #1
{
__svend_clist_pos_max:fn
{
__svend_clist_pos_max:nw { -c_max_int }
#1 , q_recursion_tail , q_recursion_stop
} {#1}
}
cs_new:Npn __svend_clist_pos_max:nw #1#2 ,
{
quark_if_recursion_tail_stop_do:nn {#2} {#1}
fp_compare:nNnTF {#2} > {#1}
{ __svend_clist_pos_max:nw {#2} }
{ __svend_clist_pos_max:nw {#1} }
}
cs_new:Npn __svend_clist_pos_max:nn #1#2
{
__svend_clist_pos_max:nnw { 1 } {#1}
#2 , q_recursion_tail , q_recursion_stop
}
cs_generate_variant:Nn __svend_clist_pos_max:nn { f }
cs_new:Npn __svend_clist_pos_max:nnw #1#2#3 ,
{
quark_if_recursion_tail_stop_do:nn {#3} {#1}
int_compare:nNnT {#2} = {#3}
{ use_i_delimit_by_q_recursion_stop:nw {#1} }
__svend_clist_pos_max:fnw { int_eval:n { #1 + c_one } } {#2}
}
cs_generate_variant:Nn __svend_clist_pos_max:nnw { f }
cs_new:Npn __svend_list_max:nw #1#2 ,
{
quark_if_recursion_tail_stop_do:nn {#2} {#1}
int_compare:nNnTF {#2} > {#1}
{ __svend_list_max:nw {#2} }
{ __svend_list_max:nw {#1} }
}
ExplSyntaxOff
defvalueA{7}
defvalueB{19}
defvalueC{41}
defvalueD{31}
defvalueE{25}
defvalueF{17}
defvalueG{7}
defvalueH{3}
begin{document}
maxposition{valueA,valueB,valueC,valueD,valueE,valueF,valueG,valueH}
end{document}
The idea is first to find the largest entry using one mapping, then to find the position of this entry using a second mapping. Everything is expandable at the code level, so you could use DeclareExpandableDocumentCommand
here if you wanted.
Correct answer by Joseph Wright on May 28, 2021
Here is an etoolbox
:
documentclass{article}
usepackage{expl3,etoolbox}
ExplSyntaxOn
cs_new_eq:NN calc fp_eval:n
ExplSyntaxOff
defvalueA{7}
defvalueB{19}
defvalueC{41}
defvalueD{31}
defvalueE{25}
defvalueF{17}
defvalueG{7}
defvalueH{3}
makeatletter
newcounter{maxindex}
newcommand{findmaxindex}[1]{%
@tempcnta=0% Counter for stepping through elements
setlength{@tempdima}{-maxdimen}% "Smallest" number as a length/dimension
renewcommand*{do}[1]{%
advance@tempcnta by 1% Step to next element
ifdimgreater{##1pt}{@tempdima}{setlength{@tempdima}{##1pt}setcounter{maxindex}{@tempcnta}}{}}% Found larger element
docsvlist{#1}% process list to find maximum number and index
}
makeatother
setlength{parindent}{0pt}% Just for this example
begin{document}
I have the list
[
7, 19, 41, 31, 25, 17, 7, 3
]
in which the largest element is $calc{max(7, 19, 41, 31, 25, 17, 7, 3)}$.
findmaxindex{7, 19, 41, 31, 25, 17, 7, 3}% Find maximum number index
The position number of the largest element in this themaxindex.
bigskip
I have the list
[
valueH,valueG,valueF,valueE,valueD,valueC,valueB,valueA
]
in which the largest element is $calc{max(valueH,valueG,valueF,valueE,valueD,valueC,valueB,valueA)}$.
findmaxindex{valueH,valueG,valueF,valueE,valueD,valueC,valueB,valueA}% Find maximum number index
The position number of the largest element in this themaxindex.
end{document}
Note that it will choose as index of the first elements that is largest. The index of the maximum number is stored in the counter maxindex
, available for print via themaxindent
.
The idea is to step through the list and mark each element that is found to be greater than the previous greatest element found. Using dimensions allows for working with decimal numbers.
Answered by Werner on May 28, 2021
Another expandable solution. No package used. (for this situation dealing only with integers, for decimals one can replace ifnum
with ifdim
up to some extent; for even more complicated situations there is, among others, xint
).
documentclass{article}
defvalueA{7}
defvalueB{19}
defvalueC{41}
defvalueD{31}
defvalueE{25}
defvalueF{17}
defvalueG{7}
defvalueH{3}
defmylist{valueA,valueB,valueC,valueD,valueE,valueF,valueG,valueH}
makeatletter
% the two routines maxoflist and maxposition are not optimal if the
% list elements require some costly expansion to compute their values
% this could be improved, if needed, to do this expansion only once
% I here design the thing for either litteral digit tokens or
% count registers or the like
% naturally one could also do a single routine with a two element
% output: (earliest) position and value of the maximum
% maximum
defmaxoflist #1{romannumeral0expandafter
maxoflist@aromannumeral-`0#1,,}
defmaxoflist@a #1,{maxoflist@c {numexpr#1relax}}
defmaxoflist@c #1#2,{%
ifxrelax #2relaxexpandaftermaxoflist@end
elseifnum#2>#1expandafterexpandafterexpandaftermaxoflist@update
elseexpandafterexpandafterexpandaftermaxoflist@next
fifi {#1}{#2}}
defmaxoflist@end #1#2{expandafterspacethe#1}
defmaxoflist@update #1#2{maxoflist@c {numexpr#2relax}}
defmaxoflist@next #1#2{maxoflist@c {#1}}
% max position
defmaxposition #1{romannumeral0expandafter
maxposition@aromannumeral-`0#1,,}
defmaxposition@a #1,{maxposition@c 21{numexpr#1relax}}
defmaxposition@b #1%
{expandaftermaxposition@cexpandafter {thenumexpr #1+@ne}}%
defmaxposition@c #1#2#3#4,{%
ifxrelax #4relaxexpandaftermaxposition@end
elseifnum#4>#3expandafterexpandafterexpandaftermaxposition@update
elseexpandafterexpandafterexpandaftermaxposition@next
fifi {#1}{#2}{#3}{#4}}
defmaxposition@end #1#2#3#4{ #2}
defmaxposition@update #1#2#3#4{maxposition@b {#1}{#1}{numexpr#4relax}}
defmaxposition@next #1#2#3#4{maxposition@b {#1}{#2}{#3}}
makeatother
begin{document}
noindent I have the list
[
mylist
]
in which the largest element is $maxoflistmylist$ (but that is
of no importance to me).[baselineskip]
How can I get LaTeX{} to extracting the position number
of the largest element in a list? (In the example above,
the answer is of course `$maxpositionmylist$'.)
end{document}
Answered by user4686 on May 28, 2021
With pgfmath
:
documentclass[a4paper]{article}
usepackage{tikz}
begin{document}
defmylist{7, 19, 41, 31, 25, 17, 7, 3}
pgfmathtruncatemacroMax{max(mylist)}
foreach[count=Pos] k in mylist {
pgfmathsetmacrotest{k==Max ? Pos : 0}
ifnumtest=0 else xdefMaxPos{test} fi
}
In {mylist} the maximum is {Max} at list-position MaxPos.
end{document}
Answered by cis on May 28, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP