![列表中最大元素的位置](https://linux22.com/image/306825/%E5%88%97%E8%A1%A8%E4%B8%AD%E6%9C%80%E5%A4%A7%E5%85%83%E7%B4%A0%E7%9A%84%E4%BD%8D%E7%BD%AE.png)
考虑以下:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{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}
笔记
它不一定是 LaTeX 3 解决方案,但我需要通过latex
--> dvips
-->编译原始文档(即我需要解决方案的文档) ps2pdf
。
此外,该列表是通过该\def
方法生成的。
答案1
我们可以使用一个或两个循环来expl3
实现这一点。一个循环版本需要计算出最大值并同时跟踪位置:
\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
\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}
\begin{document}
\maxposition{\valueA,\valueB,\valueC,\valueD,\valueE,\valueF,\valueG,\valueH}
\end{document}
而双循环版本首先找到最大值,然后找到位置,因此一次跟踪的东西更少
\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
\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}
\begin{document}
\maxposition{\valueA,\valueB,\valueC,\valueD,\valueE,\valueF,\valueG,\valueH}
\end{document}
其思路是首先使用一个映射找到最大的条目,然后使用第二个映射找到该条目的位置。一切都可以在代码级别扩展,因此您可以\DeclareExpandableDocumentCommand
根据需要在这里使用。
答案2
这是一个etoolbox
:
\documentclass{article}
\usepackage{expl3,etoolbox}
\ExplSyntaxOn
\cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff
\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{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}
请注意,它将选择作为索引第一的最大的元素。最大数字的索引存储在计数器中maxindex
,可通过打印\themaxindent
。
其思路是遍历列表并标记每个被发现大于前一个最大元素的元素。使用维度允许处理十进制数。
答案3
另一个可扩展的解决方案。没有使用任何包。(对于这种情况,仅处理整数,对于小数,可以\ifnum
在\ifdim
一定程度上用 替换;对于更复杂的情况,其中包括xint
)。
\documentclass{article}
\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}
\def\mylist{\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
\def\maxoflist #1{\romannumeral0\expandafter
\maxoflist@a\romannumeral-`0#1,,}
\def\maxoflist@a #1,{\maxoflist@c {\numexpr#1\relax}}
\def\maxoflist@c #1#2,{%
\ifx\relax #2\relax\expandafter\maxoflist@end
\else\ifnum#2>#1\expandafter\expandafter\expandafter\maxoflist@update
\else\expandafter\expandafter\expandafter\maxoflist@next
\fi\fi {#1}{#2}}
\def\maxoflist@end #1#2{\expandafter\space\the#1}
\def\maxoflist@update #1#2{\maxoflist@c {\numexpr#2\relax}}
\def\maxoflist@next #1#2{\maxoflist@c {#1}}
% max position
\def\maxposition #1{\romannumeral0\expandafter
\maxposition@a\romannumeral-`0#1,,}
\def\maxposition@a #1,{\maxposition@c 21{\numexpr#1\relax}}
\def\maxposition@b #1%
{\expandafter\maxposition@c\expandafter {\the\numexpr #1+\@ne}}%
\def\maxposition@c #1#2#3#4,{%
\ifx\relax #4\relax\expandafter\maxposition@end
\else\ifnum#4>#3\expandafter\expandafter\expandafter\maxposition@update
\else\expandafter\expandafter\expandafter\maxposition@next
\fi\fi {#1}{#2}{#3}{#4}}
\def\maxposition@end #1#2#3#4{ #2}
\def\maxposition@update #1#2#3#4{\maxposition@b {#1}{#1}{\numexpr#4\relax}}
\def\maxposition@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 $\maxoflist\mylist$ (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 `$\maxposition\mylist$'.)
\end{document}
答案4
和pgfmath
:
\documentclass[a4paper]{article}
\usepackage{tikz}
\begin{document}
\def\mylist{7, 19, 41, 31, 25, 17, 7, 3}
\pgfmathtruncatemacro\Max{max(\mylist)}
\foreach[count=\Pos] \k in \mylist {
\pgfmathsetmacro\test{\k==\Max ? \Pos : 0}
\ifnum\test=0 \else \xdef\MaxPos{\test} \fi
}
In \{\mylist\} the maximum is {\Max} at list-position \MaxPos.
\end{document}