Macro returning array with vertical line

arraysmacrosmath-modematrices

I want to make a macro "mymacro" that returns an array with two rows.
The macro has two variables and each variable is a string word composed with "b","o", "x", "|". These strings represent "blank", "\bigcirc", "\bigotimes", "vertical line partitioning one row".
The number of columns is arbitrary and equals to the number of "b,o,x" in one of the two variables and each variable has the same number of columns. Note that "|" does not affect the number of the columns.

For example,

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

should returns

enter image description here
and this code is following.

\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}

This example is three columns case. I refereed to this question for the vertical line.

I tried to apply the answers of similar question, but I was not familar with Tex macro programing and could not solve the above problem.

Thank you for your cooperations.

Best Answer

This is extensible by adding character translations. It uses the standard array environment.

The idea is to change an input such as |bo|x| into

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

where the last function translates b into a phantom, just to be sure it occupies the same space as the other characters, o into \bigcirc and x into \bigotimes.

The search regular expression means: find zero or one occurrences of | followed by a letter and zero or one occurrences of |. This is replaced by \multicolumn as shown above. At the end of this multiple replacement we need to remove an unwanted trailing &.

The number of columns is computed by examining the arguments and passing +1 for anything that's not |.

\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}

In the image, the third array is “hand made” to show the result is the same as with the second array done with \mymacro.

enter image description here

Related Question