宏返回带有垂直线的数组

宏返回带有垂直线的数组

我想创建一个宏“mymacro”,它返回一个包含两行的数组。该宏有两个变量,每个变量都是由“b”、“o”、“x”、“|”组成的字符串。这些字符串代表“blank”、“\bigcirc”、“\bigotimes”、“垂直线分割一行”。列数是任意的,等于两个变量之一中的“b,o,x”的数量,每个变量具有相同的列数。请注意,“|”不会影响列数。

例如,

\mymacro{|bo|x|}{o|x|b}

应该返回

在此处输入图片描述 代码如下。

\documentclass[amsmath]{article}
%for vertical line
\def\vl{\hfil\kern\arraycolsep\vline\kern-\arraycolsep\hfilneg}

\begin{document}
$
\begin{array}{cccc}
   \vl&            & \bigcirc \vl   & \bigotimes \vl  \\\cline{2-4}
      &\bigcirc \vl& \bigotimes \vl & 
\end{array}
$
\end{document}

本例是三列的情况。我参考了这个问题为垂直线。

我尝试应用类似问题,但我对Tex宏编程不熟悉,无法解决上述问题。

谢谢您的合作。

答案1

可通过添加字符翻译进行扩展。它使用标准array环境。

这个想法是将输入更改|bo|x|

\multicolumn{1}{|c}{\__fukai_mymacro_char:n{b}} &
\multicolumn{1}{c|}{\__fukai_mymacro_char:n{o}} &
\multicolumn{1}{c|}{\__fukai_mymacro_char:n{x}}

其中最后一个函数转换b为幻像,只是为了确保它与其他字符占据相同的空间,o进入\bigcircx进入\bigotimes

搜索正则表达式的意思是:找到零个或一个|后跟字母的 ,以及零个或一个|。如上所示,将其替换为\multicolumn。在多次替换的最后,我们需要删除不需要的尾随&

+1通过检查参数并传递任何不是的内容来计算列数|

\documentclass{article}
\usepackage{array}

\ExplSyntaxOn

\NewDocumentCommand{\mymacro}{mm}
 {
  \fukai_mymacro:nn { #1 } { #2 }
 }

\tl_new:N \l__fukai_mymacro_a_tl
\tl_new:N \l__fukai_mymacro_b_tl

\cs_new_protected:Nn \fukai_mymacro:nn
 {
  % normalize the input
  \__fukai_mymacro_normalize:Nn \l__fukai_mymacro_a_tl { #1 }
  \__fukai_mymacro_normalize:Nn \l__fukai_mymacro_b_tl { #2 }
  % start the array with the suitable number of columns
  \begin{array}
   {
    * { \int_max:nn { \__fukai_mymacro_count:n { #1 } } { \__fukai_mymacro_count:n { #1 } } } { c }
   }
   \tl_use:N \l__fukai_mymacro_a_tl
   \\ \hline
   \tl_use:N \l__fukai_mymacro_b_tl
   \end{array}
 }

\cs_new_protected:Nn \__fukai_mymacro_normalize:Nn
 {
  \tl_set:Nn #1 { #2 }
  \regex_replace_all:nnN 
   { (\|)??([[:alpha:]])(\|?) } % |<char>|
   { \c{multicolumn}\{1\}\{\1 c \3\}\{ \c{__fukai_mymacro_char:n}\{\2\} \} \& }
   #1
  \regex_replace_once:nnN { \& \Z } { } #1
 }
% count the non-| characters
\cs_new:Nn \__fukai_mymacro_count:n
 {
  \int_eval:n { 0 + \str_map_function:nN { #1 } \__fukai_mymacro_ischar:n }
 }
\cs_new:Nn \__fukai_mymacro_ischar:n
 {
  \str_if_eq:nnF { #1 } { | } { +1 }
 }
% the translations
\cs_new:Nn \__fukai_mymacro_char:n
 {
  \str_case:nn { #1 }
   {
    {b}{\phantom{\bigcirc}}
    {o}{\bigcirc}
    {x}{\bigotimes}
   }
 }

\ExplSyntaxOff

\begin{document}

$\mymacro{|b|b|ooo|x|}{oooooo}$

\bigskip

$\mymacro{|bo|x|}{o|x|b}$

\bigskip

$
\begin{array}{ccc}
\multicolumn{1}{|c}{} & \multicolumn{1}{c|}{\bigcirc} & \multicolumn{1}{c|}{\bigotimes}
\\\hline
\multicolumn{1}{c|}{\bigcirc} & \multicolumn{1}{c|}{\bigotimes} & \multicolumn{1}{c}{}
\end{array}
$

\end{document}

在图像中,第三个数组是“手工制作的”,以显示结果与第二个数组完成的结果相同\mymacro

在此处输入图片描述

答案2

例如,你可以尝试下面的代码。这里使用了 TeX 原语。

\def\mymacro{\vbox\bgroup \mymacroA}
\def\mymacroA#1{\hbox{\mystrut\mymacroB#1\relax}\futurelet\next\mymacroE}
\def\mymacroB#1{\ifx\relax#1\else \mymacroC{#1}\expandafter\mymacroB\fi}
\def\mymacroC#1{\ifx b#1\mymacroD{}\fi
                \ifx o#1\mymacroD{\bigcirc}\fi
                \ifx x#1\mymacroD{\bigotimes}\fi
                \ifx |#1\kern-.2pt\vrule\kern-.2pt\fi
}
\def\mymacroD#1{\hbox to2em{$\hss#1\hss$}}
\def\mymacroE{\ifx\next\bgroup\hrule\expandafter\mymacroA\else\egroup\fi}
\def\mystrut{\vrule height2ex depth1ex width0pt\relax}

%% test:
\mymacro{|bo|x|}{o|x|b}

\end

答案3

这种方法是,两行符号之间的水平线与两行中较长的一行一样长:

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\UD@stopromannumeral\@secondoftwo}{%
  \expandafter\UD@stopromannumeral\@firstoftwo}%
}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%

\newcommand\UD@symbolbox[1]{\vbox to2em{\vss\hbox to 2em{\hss#1\hss}\vss}}%

\@ifdefinable\UD@gobbletoexclam{\long\def\UD@gobbletoexclam#1!{}}%
\@ifdefinable\UD@replacefork{\long\def\UD@replacefork#1!|!b!o!x!#2#3!!!!{#2}}%
\@ifdefinable\UD@replaceloop{%
  \long\def\UD@replaceloop#1#2#3\bizarre{%
    \UD@CheckWhetherNull{#3}{#1{\phantom}\vrule}{%  
      \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoexclam#2!}{%
        \UD@replacefork!#2!b!o!x!{\UD@replaceloop{\@gobble}}%
                       !|!#2!o!x!{#1{\phantom}\vrule\UD@symbolbox{$\hss$}\UD@replaceloop{\@firstofone}}%
                       !|!b!#2!x!{#1{\phantom}\vrule\UD@symbolbox{$\bigcirc$}\UD@replaceloop{\@firstofone}}%
                       !|!b!o!#2!{#1{\phantom}\vrule\UD@symbolbox{$\bigotimes$}\UD@replaceloop{\@firstofone}}%
                       !|!b!o!x!{\UD@replaceloop{#1}}%
                       !!!!%
      }{\UD@replaceloop{#1}}#3\bizarre
    }%
  }%
}%
\@ifdefinable\UD@loopoverrows{%
  \long\def\UD@loopoverrows#1#2#3#4#5\bizarre{%
    %#1 - previous row
    %#2 - separators in current iteration
    %#3 - separators in consecutive iterations
    %#4 - current row
    %#5 - following rows
    \UD@CheckWhetherNull{#5}{}{%
      \@secondoftwo#2%
      \vbox{%
        \baselineskip=0pt \lineskip=0pt 
        \@firstoftwo#2%
        \hbox{\hphantom{\UD@replaceloop{\@firstofone}#1{{}{}}\bizarre}}%
        \hbox{\UD@replaceloop{\@firstofone}#4{{}{}}\bizarre}%
      }%     
      \UD@loopoverrows{#4}{#3}{#3}#5\bizarre
    }%
  }%
}%
\newcommand\mymacro[1]{%
  \vbox{\UD@loopoverrows{}{{}{}}{{\hrule}{\hrule height 0pt depth 0pt}}#1{{}{}}\bizarre}%
}%
\makeatother


\documentclass{article}
\begin{document}

\mymacro{
  {|bo|x|}
  {o|b|xo|b}
  {x|o|b}
  {o|x|b}
  {o|x|b|oxbx}
  {|x|b|x|}
}

\end{document}

带有 o/b/x 东西的矩形的高度和宽度在宏中编码\UD@symbolbox。水平规则的高度/垂直规则的宽度不包含在这些矩形的测量中。如果不需要垂直规则,则该垂直规则是幻影。

在此处输入图片描述

相关内容