2

I would like to do the same sort of thing as in the question How to create table column wise in LaTeX?, except that I want to do it in math mode.

To be precise: I want to enter an array of items of possibly different sizes, similar to the matrix environment, except that in the LaTeX source code I want to specify one column of items and the next column, and so on, instead of specifying the items by row as usual. I want the result to be vertically centered like the matrix environment.

I also want to be able to specify the amount of horizontal and vertical space between the items.

Here is an mwe to show what I mean.

\documentclass{article}
\usepackage{amsmath}
\begin{document}

\begin{equation} x = \begin{matrix} 1 & 4 \ 2 & 5 \ 3 & \Big(6\Big) \ \end{matrix} \end{equation}

\end{document}

In this LaTeX code, the items appear in the order 1, 4, 2, 5, 3, 6, but I want to specify them in the order 1, 2, 3, 4, 5, 6.

(Actually, even better than that would be 3, 2, 1, 6, 5, 4 - column-wise but with the columns specified in reverse order. But I can imagine this being difficult and will be happy enough with the 1, 2, 3, 4, 5, 6 order.)

Here's what the mwe output looks like.

enter image description here

There is a related question, Is there a way to automatically transpose a matrix written in Latex?, but because that question is asking specifically about transposing a matrix, the answers don't end up having a way to specify the space between elements. I'm hoping for a simpler solution along the lines of the top answer at How to create table column wise in LaTeX?, which is more about stacking boxes on top of each other than doing hefty expl3 stuff.

N. Virgo
  • 4,289
  • 2
  • 26
  • 41
  • I know no way to make that automagically, but you can type your matrix content with three columns and two rows. – Bernard Aug 09 '22 at 11:30
  • You seems to be familiar with Python, so just use PythonTeX to implement a macro to do that. Should be easy right – user202729 Aug 09 '22 at 11:38
  • @user202729 right, it's completely straightforward in PythonTeX, but I'm looking for a pure LaTeX solution because PythonTeX has compatibility issues with Overleaf and also with arXiv. – N. Virgo Aug 09 '22 at 12:43
  • it's easy to arrange a macro that specifies 2x6 matrix in any order, a bit harder to to the general case – David Carlisle Aug 09 '22 at 13:28
  • @F.Pantigny that's linked in my question already. – N. Virgo Aug 09 '22 at 14:35
  • Although I hadn't seen @wipet's valign answer to that previous question, which is useful. – N. Virgo Aug 09 '22 at 14:37

4 Answers4

1

\valign primitive was designed for such a task:

\def\iskip{\vskip2pt plus1fil}
$$
  x = 
  \vcenter{\hbox{\valign{&\iskip\hbox to1.5em{\hss$#$\hss}\iskip\cr
     1 & 2 & 3 \cr
     4 & 5 & (6) \cr
  }}}
$$

\bye

wipet
  • 74,238
1

You can even use the proposed syntax (bottom up):

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand{\rmatrix}{O{2}m} {% #1 is the number of columns, default 2 % #2 is a comma separated list of items \virgo_rmatrix:nn { #1 } { #2 } }

\seq_new:N \l__virgo_rmatrix_items_seq \tl_new:N \l__virgo_rmatrix_body_tl \int_new:N \l__virgo_rmatrix_rows_int

\cs_new_protected:Nn \virgo_rmatrix:nn { % this will contain the body \tl_clear:N \l__virgo_rmatrix_body_tl % make a sequence from the items \seq_set_from_clist:Nn \l__virgo_rmatrix_items_seq { #2 } % check if the number of items is a multiple of #1 \int_compare:nF { \int_mod:nn { \seq_count:N \l__virgo_rmatrix_items_seq } { #1 } == 0 } {% not a multiple, pad \prg_replicate:nn { #1 - \int_mod:nn { \seq_count:N \l__virgo_rmatrix_items_seq } { #1 } } { \seq_put_right:Nn \l__virgo_rmatrix_items_seq { } } } % determine the number of rows \int_set:Nn \l__virgo_rmatrix_rows_int { \int_div_truncate:nn { \seq_count:N \l__virgo_rmatrix_items_seq } { #1 } } % read the items \int_step_inline:nnnn { \l__virgo_rmatrix_rows_int } { -1 } { 1 } {% ##1 is the row index \int_step_inline:nnn { 0 } { #1 - 1 } {% ####1 is the column index minus 1 \tl_put_right:Nx \l__virgo_rmatrix_body_tl { \seq_item:Nn \l__virgo_rmatrix_items_seq { ##1 + ####1*\l__virgo_rmatrix_rows_int } \int_compare:nTF { ####1 = #1 - 1 } { \exp_not:N \ } { & } } } } \begin{matrix} \tl_use:N \l__virgo_rmatrix_body_tl \end{matrix} }

\begin{document}

[ x= \rmatrix{3,2,1,\bigl(6\bigr),5,4} ]

[ x= \rmatrix[3]{3,2,1,\bigl(6\bigr),5,4} ]

[ x= \rmatrix[4]{3,2,1,\bigl(6\bigr),5,4,9,8,7,10} ]

\end{document}

The number of items is made a multiple of the number of columns, the number of rows is computed by that data.

The sequence is then traversed from every multiple of the number of rows backwards.

enter image description here

egreg
  • 1,121,712
0

Here's an imperfect self-answer, essentially formed by wrapping the answer to How to create table column wise in LaTeX? in \vcenter{\hbox{...}}.

It's imperfect because I'm just hacking away at the other answer without really understanding how it works, and also because it doesn't come out perfectly vertically centred - there must be some subtlety about \vecenter that I'm not understanding. Additionally the elements are not centred within their columns, though that's not a huge issue for me.

But on the plus side it behaves how I wanted in that the array is specified columnwise in the source, and in that it offers the desired control over spacing.

\documentclass{article}
\usepackage{amsmath}

\newenvironment{colarray}[2]{% \vcenter\bgroup\hbox\bgroup\valign\bgroup&\vfil\vbox{\parindent=0pt\tabskip=#2\hsize=#1##}\vfil\cr}% {\egroup\egroup\egroup} \newcommand*\col[1]{#1\cr}

\begin{document}

\begin{equation} x = \begin{colarray}{4mm}{2mm} \col{1 & 2 & 3} \col{4 & 5 & \Big(6\Big)} \end{colarray} \end{equation}

\end{document}

enter image description here

update: I figured out the vertical spacing issue. There needs to be a negative vskip to cancel out the tabskip on the last row. Unfortunately that means it has to be a newcommand and not a newenvironment, but here it is:

\documentclass{article}
\usepackage{amsmath}

% this can't be an environment because the code for \end can't have parameters. \newcommand{\colarray}[3]{ \vcenter{\hbox{\valign{&\vfil\vbox{\parindent=0pt\tabskip=#2\hsize=#1##}\vfil\cr% #3% }}\vskip-#2}% }

\newcommand*\col[1]{#1\cr}

\begin{document}

\begin{equation} x = \colarray{4mm}{2mm}{ \col{1 & 2 & 3} \col{4 & 5 & \Big(6\Big)} } \end{equation}

\end{document}

enter image description here

Now it's just the horizontal centering within cells that I need to figure out.

N. Virgo
  • 4,289
  • 2
  • 26
  • 41
  • Talk about the "understanding" part if you really want to, start with the TeXbook. (not free though. There's TeX by Topic but covers the primitives only) – user202729 Aug 09 '22 at 14:52
  • @user202729 I read it once (or part of it at least), when I was a student and had time on my hands. But that was well over a decade ago and I can't remember any of it. – N. Virgo Aug 09 '22 at 14:58
0

This is not really an answer, but too long for a comment. Hopefully it can be useful for somebody, perhaps somebody can cook up a solution for lualatex?

In ConTeXt there has for a while been possible to transpose matrices. We can define a matrix type that is transposed (done in lua) as

\definemathmatrix[virgomatrix][
    action=transpose,
    simplecommand=virgomatrix,
    distance=4em,
]

Once that is done we can add a transposed matrix with

\dm{ x = \virgomatrix{1,2,3; 4,5,\Bigl( 6 \Bigr); 7,8} }

Output: Transposed matrix

If we also want to change the order of the rows we need to have a look at math-ali.lmt where this is defined. There we find

local actions = {
    transpose = function(m)
        local t = { }
        for j=1,#m[1] do
            local r = { }
            for i=1,#m do
                r[i] = m[i][j]
            end
            t[j] = r
        end
        return t
    end,
...
}

where the three dots is just indicating that some parts are being left out.

We can imitate this and define our own "Virgo" action (note the small change in r[i]).

\startluacode
    mathematics.registersimplematrix("Virgo",function(m)
        local t = { }
        for j=1,#m[1] do
            local r = { }
            for i=1,#m do
                r[i] = m[i][#m[1]-j+1]
            end
            t[j] = r
        end
        return t
    end)
\stopluacode

Then we can use it. We define a new type of matrix, the Virgo matrix.

\definemathmatrix[Virgomatrix][
    action={Virgo},
    simplecommand=Virgomatrix,
    distance=4em,
]

We then use this new type:

\dm{ x = \Virgomatrix{1,2,3;4,5,\Bigl( 6 \Bigr);7,8} }

The output is shown below. a Virgo matrix

mickep
  • 8,685