3

I would like to automatically create structures like this: enter image description here

The picture above have been generated with NiceTabular:

\begin{NiceTabular}{cccc}[hvlines,corners=SW]
\NotEmpty &  &  &   \\
& \NotEmpty   &  &  \\
&   & \NotEmpty   &  \\
&   &   & \NotEmpty   \\
&   &   &   \\
\end{NiceTabular}

I would like to, instead of writing the cells one by one, have a command to automatically generate the contents following the pattern. For example, with a block like this:

\begin{uppertriangle}{4}
\end{uppertriangle}

Such that it generates the above plot. The number {4} would be the length of the first row, and the length of each subsequent row must be of decreasing lengths 1 by 1. I would also like to be able to write stuff and manipulate the contents of the generated array as I can do with NiceTabular (notice, by the way, that the first cell is not correctly sized; this wasn't me):

enter image description here

Generated by this:

\begin{NiceTabular}{cccc}[hvlines,corners=SW]
\CodeBefore
\cellcolor[HTML]{FFFF88}{1-2,1-3,2-3,2-4,4-4}
\Body
\NotEmpty & 1 & 1 &   \\
& \NotEmpty   & 1 & 1 \\
&   & \NotEmpty   & 1 \\
&   &   & \NotEmpty   \\
&   &   &   \\
\end{NiceTabular}
Bernard
  • 271,350
ABu
  • 1,625
  • 2
    I don't know what you exactly mean by : the first cell is not correctly sized. The output is as expected since that cell is in a column whose all cells are empty. If you want all the columns with the same width, use columns-width=auto. – F. Pantigny Oct 08 '22 at 18:00
  • 1
    Do you just need the squares or do you actually want to input numbers? Is it okay if you have to add & even if the cell is empty? Just by using & and \\ you already specify how many rows and cells you need. – Qrrbrbirlbel Oct 08 '22 at 20:11
  • @Qrrbrbirlbel Yes, I need the squares. About the second, well, it simplifies it a bit but not so much. I'm printing upper diagonal of matrices, and a perfect solution would be one that automatically prints such upper diagonal only by specifying its order and also that could allow me to refer to cells in terms of coordinates to personalize their visual aspects and contents cells-wise. – ABu Oct 08 '22 at 21:23

4 Answers4

3

Those structures are usually called Young tableaux and you can use the ytableau or youngtab packages to draw them.

\documentclass{article}
\usepackage{ytableau}

\colorlet{yty}{yellow!60} % Young Tableau Yellow

\begin{document}

[ \ydiagram{4,1+3,2+2,3+1} ]

[ \begin{ytableau} {} & (yty) 1 & (yty) 1 & {} \ \none & & (yty) 1 & (yty) 1 \ \none & \none & {} & 1 \ \none & \none & \none & *(yty) {} \end{ytableau} ]

\end{document}

In the first case we're specifying four cells in the first row, three in the second one with a offset by one and so on. The second tableau has explicit entries; with \none the frame is not drawn.

enter image description here

egreg
  • 1,121,712
3

Here is a TikZ solution that creates a tikzpicture, but not a matrix.

enter image description here

The command is \uppertriangle[<contents>]{<rows>}

<rows> is required and should be a positive integer (number of rows). <contents> is an optional comma-separated list whose entries have the form

<row>-<column>/<entry>/<fill color>.

For example, the middle figure is created with the command

\uppertriangle[1-3/A/yellow,3-2/B/red,2-1/C/none]{4}.

Note that the columns are indexed from right to left. Cell size is controlled globally with \cellsize (currently set to .75cm).

\documentclass{article}

\usepackage{tikz} \tikzset{cell/.style={draw, minimum size=\cellsize, fill=#1}, cell/.default={none}}

\newcommand{\cellsize}{.75cm} \newcommand{\uppertriangle}[2][]{\tikz[]{ \foreach \n[count=\j] in {#2,...,1} \foreach \m[count=\k] in {1,...,\n} {\nodecell at (\cellsize\n,-\cellsize\m){};} \foreach \c/\d/\s in {#1}{\node[cell=\s]at(A\c){\d};} }}

\begin{document}

\uppertriangle{4}\qquad \uppertriangle[1-3/A/yellow,3-2/B/red,2-1/C/none]{4}\qquad \uppertriangle[1-2/1/yellow,2-4/1/orange,3-1/1/cyan]{5}

\end{document}

Sandy G
  • 42,558
3

I implement the macro \utriangle with single parameter which gives the number of cells in the first row.

\utrinagle 4

prints the triangle as shown in the question. \utrianhle 7 prints more bigger triangle, etc.

Before using \utriangle, you can use \utriangledecl and \utrianglecolors in order to declare the contents of the cells. The example shown in the question can be printed by:

\utriangledecl {
  . 1 1 .
    . 1 1
      . 1
        .  
}
\colorlet{y}{yellow!60}
\utrianglecolors {
   . y y .
     . y y
       . .
         y
}
\utriangle 4

The cell-parameters used by \utrianglecell and \utrianglecolors are spaces separated. The dot means empty parameter. You can arrange them to a triangle in order to keep the readability. For example:

\utriangledecl {
   .  x_1     x_2     .
      x_{12}  x_{13}  .
              .       .
                      x_7
}
\utriangle 4

Note that the parameters are printed in math mode.

The size of the result depends on \cellw register which denotes width and height of the single cell. Default is \cellw=17pt

The implementation doesn't depend on LaTeX macros but it can be used in LaTeX too. Colors macros in only one exception, they depend on the used format.

\documentclass{article}
\usepackage{xcolor}

\newcount\cellnum \newcount\tmpnum \newdimen\cellw \cellw=17pt

\def\utriangle#1 {% \vbox{\chardef\uwidth=#1 \offinterlineskip \tmpnum=#1 \cellnum=0 \hrule \printrow } } \def\printrow{\hbox to\the\uwidth\cellw{\hss \printcell} \advance\tmpnum by-1 \ifnum\tmpnum>0 \expandafter \printrow \fi } \def\printcell{\global\advance\cellnum by1 \singlecell \advance\tmpnum by-1 \ifnum\tmpnum>0 \expandafter \printcell \else \vrule \fi } \def\singlecell{\vbox{\hbox to\cellw{% \ifcsname cellcolor:\the\cellnum \endcsname \rlap{\color{\csname cellcolor:\the\cellnum\endcsname}% <-- format dependent part \vrule height.7\cellw depth.3\cellw width\cellw}% \fi \vrule height.7\cellw depth.3\cellw \hss $\csname cell:\the\cellnum\endcsname$\hss}\kern-.4pt\hrule}% \global \expandafter\let \csname cell:\the\cellnum\endcsname \undefined \global \expandafter\let \csname cellcolor:\the\cellnum\endcsname \undefined }

\def\utriangledecl #1{\cellnum=0 \def\prefix{cell}\declcell #1 {\end} } \def\utrianglecolors #1{\cellnum=0 \def\prefix{cellcolor}\declcell #1 {\end} } \def\declcell#1 {% \advance\cellnum by1 \ifx\end#1\relax \else \ifx &#1&\advance\cellnum by-1 \else \ifx .#1\relax \else \expandafter\def\csname\prefix:\the\cellnum\endcsname{#1}\fi\fi \expandafter\declcell \fi }

\begin{document}

%%% tests: \utriangledecl { . 1 2 . . 1 1 . 1 .
} \colorlet{y}{yellow!60} \utrianglecolors { . y y . . y y . . y } \utriangle 4

\utriangle 14

\utriangledecl { . x_1 x_2 . x_{12} x_{13} . . . x_7 } \utriangle 4

\end{document}

wipet
  • 74,238
2

This solution allows you to specify the number of columns and rows with its mandatory argument.

The environments are uppertriangle and lowertriangle. Their optional argment will be forwarded to the internal \matrix.

The \\ – the \pgfmatrixendrow macro actually – will be patched in a way that you don't have to add empty cells at the start or the end of the row. Empty cells will be inserted on both ends automatically.

The matrix is setup in a way with execute at empty cell, execute at begin cell and execute at end cell that only the actual cells have a possible empty node in them. These use the macros that also matrix of nodes use so you should be able to use |[<options]| as usual in a node.

Don't use matrix of math nodes, though, this will be in conflict with triangle matrix/triangle setup. Just use

math nodes/.style={
  nodes={
    execute at begin node=$,%
    execute at end node=$%
  }
}

My ext.node-families library helps make all nodes in one column have the same width. There are simpler approach if you know the cell content beforehand. (Of course, we can also draw none of the nodes and loop over them afterwards and figure out where to draw the lines then.)

The style matrix like tabular sets up the nodes similar on how cells of a tabular or array would have been setup. Except that instead of \strut the height and depth of the node is set to the dimension of \strut but they don't expand if the contents are higher or deeper.

This highly depends on what the contents of your matrix will be. If you can't predict it and it may be more complex you might need to set the families node family/text height and node family/text depth as well (as I did in a previous version of this answer).


The cell color = {<list of cells>}{<color>} sets all cells in its first argument to use <color> as their fill.

This key is a specialized version of the solutions provided by another answer of mine.


Remember that in a PGF/TikZ matrix, the & is made active and isn't the usual alignment character. If you use this as part of an argument of macro, you're going to need to use ampersand replacement.

Sneak peek

The output is the result of

\begin{uppertriangle}[cell color={1-2, 1-3, 2-3, 2-4, 4-4}{yellow!60}]{4}
 & 1 & 1     \\
     & 1 & 1 \\
         & 1
\end{uppertriangle}
\begin{lowertriangle}{10}
\end{lowertriangle}

Output

enter image description here

Code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix,ext.node-families}
\makeatletter
\def\pgfutil@addto@macro#1#2{%
  \expandafter\def\expandafter#1\expandafter{#1#2}}
\tikzset{
  execute before new row/.style={% \preto
    /utils/tempa/.initial/.expand once=\pgfmatrixendrow,
    /utils/tempa/.prefix={#1}, /utils/tempa/.get=\pgfmatrixendrow},
  execute after new row/.code={% \appto
    \pgfutil@addto@macro\pgf@matrix@no@eom@found{#1}},
  triangle matrix/triangle setup/.style={
    execute before new row={
      \let\tikz@temp\pgfutil@empty \c@pgf@counta=\pgfmatrixcurrentcolumn
      \pgfutil@loop\ifnum\c@pgf@counta<\tikzmatrixrows\relax
        \pgfutil@addto@macro\tikz@temp\pgfmatrixnextcell
      \advance\c@pgf@counta1 \pgfutil@repeat\tikz@temp},
    nodes in empty cells,
    execute at empty cell={%
      \ifnum\pgfmatrixcurrentrow#1\pgfmatrixcurrentcolumn\else
        \expandafter\tikz@lib@matrix@empty@cell\fi},
    execute at begin cell={%
      \ifnum\pgfmatrixcurrentrow#1\pgfmatrixcurrentcolumn\else
        \expandafter\tikz@lib@matrix@start@cell\fi},
    execute at end cell={%
      \ifnum\pgfmatrixcurrentrow#1\pgfmatrixcurrentcolumn\else
        \expandafter\tikz@lib@matrix@end@cell\fi}},
  triangle matrix/upper triangle/.style={
    triangle matrix/triangle setup={>},
    execute after new row={%
      \let\tikz@temp\pgfutil@empty \c@pgf@counta=\pgfmatrixcurrentrow 
        \pgfutil@loop\ifnum\c@pgf@counta>1
          \pgfutil@addto@macro\tikz@temp\pgfmatrixnextcell
          \advance\c@pgf@counta-1 \pgfutil@repeat\tikz@temp}},
  triangle matrix/lower triangle/.style={triangle matrix/triangle setup={<}},
  triangle matrix/remaining rows/.initial={%
    \let\tikz@temp\pgfutil@empty
    \c@pgf@counta=\pgfmatrixcurrentrow\relax
    \pgfutil@loop
      \ifnum\c@pgf@counta<\tikzmatrixrows\relax
      \pgfutil@addto@macro\tikz@temp\pgfmatrixendrow
      \advance\c@pgf@counta1
    \pgfutil@repeat
    \tikz@temp}}
\makeatother
\tikzset{
  matrix like tabular/.style={
    /pgf/inner xsep=+\tabcolsep, /pgf/inner ysep=+0pt,
    /tikz/text height=+.7\baselineskip,% .7 and .3 → basically \strutbox
    /tikz/text depth=+.3\baselineskip},% or font=\strut
  %
  % specialized version of https://tex.stackexchange.com/a/660100
  cell color/.style 2 args={
    /utils/tempa/.style args={##1-##2}{row ##1 column ##2/.append style={nodes={fill=#2}}},
    /utils/tempa/.list={#1}},
  %
  triangle matrix/picture/.style={
    baseline=(current bounding box.center),% triangle matrix-1-1.base
    /utils/exec=\pgfmathtruncatemacro\tikzmatrixrows{#1},
    matrix like tabular},
  triangle matrix/matrix/.style={
    name=triangle matrix, every outer matrix/.append style={/pgf/inner sep=+0pt},
    column sep=+-\pgflinewidth, row sep=+-\pgflinewidth,
    nodes={draw, node family={
        prefix/.append=\tikzmatrixname,
        width=col\the\pgfmatrixcurrentcolumn}}}}

\newenvironment{uppertriangle}[2][]{% \tikzpicture[triangle matrix/picture/.evaluated={int(#2)}, triangle matrix/upper triangle] \matrix[triangle matrix/matrix,#1]\bgroup }{% \pgfkeysvalueof{/tikz/triangle matrix/remaining rows}% \pgfmatrixendrow\egroup; \endtikzpicture} \newenvironment{lowertriangle}[2][]{% \tikzpicture[triangle matrix/picture/.evaluated={int(#2)}, triangle matrix/lower triangle] \matrix[triangle matrix/matrix,#1]\bgroup }{% \pgfkeysvalueof{/tikz/triangle matrix/remaining rows}% \pgfmatrixendrow\egroup; \endtikzpicture}

\begin{document} \begin{uppertriangle}[cell color={1-2, 1-3, 2-3, 2-4, 4-4}{yellow!60}]{4} & 1 & 1 \ & 1 & 1 \ & 1 \end{uppertriangle} \begin{lowertriangle}{10} \end{lowertriangle} \end{document}

Qrrbrbirlbel
  • 119,821
  • Amazing. I will test it as soon as I can. Thank you. – ABu Oct 08 '22 at 21:49
  • I'm a programmer since more than a decade now and no language have beaten me so far... but TeX is totally unreadable witchcraft, but amazing at the same time, specially in combination with Tikz. I hope some day I learn how to master it and do the kind of trickeries you are able to, although I wonder why TeX hasn't any real alternative yet, syntactically speaking. – ABu Oct 08 '22 at 21:59