8

Consider the following PSTricks code:

\documentclass{article}

\usepackage{pstricks,multido}
\psset{dimen = m, fillstyle = solid}

\begin{document}

\begin{figure}
 \centering
  \begin{pspicture}(12,12)
    \psframe[fillcolor = orange](0,11)(1,12)
    \rput(0.5,11.5){$\cdot$}
    \multido{\iA = 1+1, \iB = 10+-1}{11}{
      \psframe[fillcolor = orange](\iA,11)(!\iA\space 1 add 12)
      \rput(!\iA\space 0.5 add 11.5){$\iA$}
      \psframe[fillcolor = orange](0,\iB)(!1 \iB\space 1 add)
      \rput(!0.5 \iB\space 0.5 add){$\iA$}
      \multido{\iC = 0+1}{11}{\psframe(\iA,\iC)(!\iA\space 1 add \iC\space 1 add)}}
  \end{pspicture}
 \caption{Multiplication table.}
\end{figure}

\end{document}

output

Questions

  • How do I automatically genrate the numbers in the multiplication table? (I've had a look at the code in section 14 of the pstricks-add manual but without any luck.)
  • How (if possible) do I automatically colour all the squares in the sequence, say, n*(n+6) (i.e., the two diagonals of squares containing the numbers 6, 14, 24, 36, 50, 66)?

P.S. If no PSTricks solution can be found, a TikZ solution is also acceptable but I prefer PSTricks. :)

Update

I should probably add that I only need rows, column, or diagonals coloured; not, say, 4, 15, 30, 49, 72, 99. (If someone can come up with code that can automatically colour such a sequence, it will of course be even better but it's not necessary.)

Update 2

Here is what I now have:

\documentclass{article}

\usepackage{pstricks,multido}
\psset{dimen = m, fillstyle = solid}

\usepackage{expl3}
\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff


\begin{document}

\def\tableSize{11}

\begin{figure}
 \centering
  \begin{pspicture}(\calc{\tableSize+1},\calc{\tableSize+1})
    \psframe[fillstyle = solid, fillcolor = orange](0,\tableSize)(1,\calc{\tableSize+1})
    \rput(0.5,\calc{\tableSize+0.5}){$\cdot$}
    \multido{\iA = 1+1, \iB = \calc{\tableSize-1}+-1}{\tableSize}{%
      \psframe[fillcolor = orange](\iA,\tableSize)(\calc{\iA+1},\calc{\tableSize+1})
      \rput(\calc{\iA+0.5},\calc{\tableSize+0.5}){$\iA$}
      \psframe[fillcolor = orange](0,\iB)(1,\calc{\iB+1})
      \rput(0.5,\calc{\iB+0.5}){$\iA$}
      \multido{\iC = 1+1}{\tableSize}{%
        \psframe(\iA,\calc{\tableSize+1-\iC})(\calc{\iA+1},\calc{\tableSize-\iC})
        \rput(\calc{\iA+0.5},\calc{\tableSize+0.5-\iC}){$\calc{\iA*\iC}$}}}
  \end{pspicture}
 \caption{Multiplication table.}
\end{figure}

\end{document}

output2


I found a PSTricks solution myself where arbitrary "horizontal", "vertical", and "diagonal" series can be colored.

Macro syntax

\tableColorRow[<row color>]{<now number>}
\tableColorColumn[<column color>]{<column number>}
\tableColorDiagonal[<diagonal color>]{<starting row/column number>}

Code

\documentclass{article}

\usepackage{pstricks,multido}
\usepackage{bm}

\psset{dimen = m, fillstyle = solid}

\usepackage{expl3}
\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

% create table
\def\tableArithmetic[#1]#2{%
  \psframe[fillcolor = #1](0,\tableSize)(1,\calc{\tableSize+1})
  \rput(0.5,\calc{\tableSize+0.5}){$\boldsymbol{#2}$}
  \multido{\iA = 1+1, \iB = \calc{\tableSize-1}+-1}{\tableSize}{%
    \psframe[fillcolor = #1](\iA,\tableSize)(\calc{\iA+1},\calc{\tableSize+1})
    \rput(\calc{\iA+0.5},\calc{\tableSize+0.5}){\fontSize $\iA$}
    \psframe[fillcolor = #1](0,\iB)(1,\calc{\iB+1})
    \rput(0.5,\calc{\iB+0.5}){\fontSize $\iA$}
    \multido{\iC = 1+1}{\tableSize}{%
      \psframe(\iA,\calc{\tableSize+1-\iC})(\calc{\iA+1},\calc{\tableSize-\iC})
      \rput(\calc{\iA+0.5},\calc{\tableSize+0.5-\iC}){\fontSize $\calc{\iA*\iC}$}%
    }%
  }%
}
% color row
\def\tableColorRow[#1]#2{%
  \multido{\i = 1+1}{\tableSize}{%
    \psframe[fillcolor = #1](\i,\calc{\tableSize-#2})(\calc{\i+1},\calc{\tableSize-#2+1})
    \rput(\calc{\i+0.5},\calc{\tableSize-#2+0.5}){\fontSize $\calc{\i*#2}$}%
  }%
}
% color column
\def\tableColorColumn[#1]#2{%
  \multido{\iA = 1+1, \iB = \calc{\tableSize-1}+-1}{\tableSize}{%
    \psframe[fillcolor = #1](#2,\iB)(\calc{#2+1},\calc{\iB+1})
    \rput(\calc{#2+0.5},\calc{\iB+0.5}){\fontSize $\calc{\iA*#2}$}%
  }%
}
% color diagonal
\def\tableColorDiagonal[#1]#2{%
  \multido{\iA = 1+1, \iB = #2+1, \iC = \calc{\tableSize-#2}+-1, \iD = \calc{\tableSize-1}+-1}{\calc{\tableSize-#2+1}}{%
    \psframe[fillcolor = #1](\iA,\iC)(\calc{\iA+1},\calc{\iC+1})
    \rput(\calc{\iA+0.5},\calc{\iC+0.5}){\fontSize $\calc{\iA*(\iA+#2-1)}$}
    \psframe[fillcolor = #1](\iB,\iD)(\calc{\iB+1},\calc{\iD+1})
    \rput(\calc{\iB+0.5},\calc{\iD+0.5}){\fontSize $\calc{\iA*(\iA+#2-1)}$}%
  }%
}

\begin{document}

\begin{figure}
\def\tableSize{11}
\def\fontSize{%
%  \Huge
%  \huge
%  \LARGE
%  \Large
%  \large
  \normalsize
%  \small
%  \footnotesize
%  \scriptsize
%  \tiny
}
 \centering
  \begin{pspicture}(\calc{\tableSize+1},\calc{\tableSize+1})
    \tableArithmetic[orange!80]{\cdot}
    \tableColorRow[blue!70]{8}
    \tableColorColumn[red!70]{2}
    \tableColorDiagonal[green!80]{6}
  \end{pspicture}
 \caption{Multiplication table.}
\end{figure}

\end{document}

Output

output

5 Answers5

8

In case TikZ needed,

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix}
\def\mcr{\pgfmatrixcurrentrow}\def\mcc{\pgfmatrixcurrentcolumn}
\begin{document}
\begin{tikzpicture}[border style/.style={
    draw,fill=#1,minimum size=0.8cm,anchor=center,outer sep=0,
    name=\tikzmatrixname-\the\mcr-\the\mcc
}]
\matrix[row sep=-.5*\pgflinewidth,column sep=-.5*\pgflinewidth,
   execute at empty cell={%
       \ifnum1=\mcr\relax%
           \ifnum1=\mcc\relax\node[border style=red]{$\cdot$};%
           \else\node[border style=red]{$\number\numexpr\the\mcc-1\relax$};\fi
       \else%
         \ifnum1=\mcc\relax\node[border style=red]{$\cdot$};%
           \node[border style=red]{$\number\numexpr\the\mcr-1\relax$};%
         \else%
           \pgfmathparse{int(abs(\mcr-\mcc))}%
           \ifnum5=\pgfmathresult\relax\def\temp{yellow}\else\def\temp{none}\fi%
           \node[border style=\temp]{\number\numexpr\numexpr\the\mcc-1\relax*\numexpr\the\mcr-1\relax\relax};%
         \fi%
       \fi}
] (a) {
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
&&&&&&&&&&&\\
};
\end{tikzpicture}
\end{document}

enter image description here

percusse
  • 157,807
  • Really nice. I don't know TikZ so can I make you explain how you colour the diagonals? Also, is it possible to create a macro, say \multiTable{<size>}{<diagonals to colour + colour used>}, to generate the table (since I need more of them)? – Svend Tveskæg Jun 01 '15 at 08:12
  • @SvendTveskæg It is cheating. If the difference between the row number and the column number is exactly 5 then I change the fill color. It is the last part of the if branch. It is the index of the 5th sub super diagonal. – percusse Jun 01 '15 at 08:16
  • Okay. I'll have a look at it; thank you very much. – Svend Tveskæg Jun 01 '15 at 08:20
  • Very nice. Is there a way to change the code slightly to avoid having to hard code the ampersands? that is, replacing the lines&&&&&&&&&&&\\ with something 'more general', so that the size of the matrix could be changed without having to recode? Thanks. (I can ask a separate question if you think it deserves it!) – PatrickT May 20 '16 at 10:19
8

This seems like overkill (and it is) but you have high customizability.

The automatic building of the matrix is done via two loops that adds the correct amount of \pgfmatrixnextcells and \\s in one macro that solely is given to the matrix content. There might be better ways, but this is the easiest I have found for now.

\pgfmathloop is—as far as I know—LaTeX’s \loop with an included counter (\pgfmathcounter, a macro) and does not group and is very much without any other functionality like PGF’s own \foreach, but for this it suffices.

There is much more room for improvement like hiding the \pgfmatrix… internals from the outside, e.g. interacting with the headings in a separate way, having the first row be the actual first row with contents, etc.

I have added a second diagram that uses the function rowcolumns for calculating a cell’s content. The second column (i.e. the first after the header column) is altered with the style

column 2/.style={coordinate, column sep=+0pt},

which changes the column sep back to zero (the -\pgflinewidth sep is needed as you want the lines to overlap) and applies coordinate (i.e. shape=coordinate) to the nodes with essentially eliminates the node (and its text). Of course TikZ still creates a named coordinate and all …

Here further functions for the columns/rows would be helpful.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{matrix}
\tikzset{
  if/.code n args=3{\pgfmathparse{#1}\ifnum\pgfmathresult=0
    \pgfkeysalso{#3}\else\pgfkeysalso{#2}\fi},
  set column text width/.style={
    /utils/exec=\pgfmathtruncatemacro\multiTableTempa{#1-1}%
                \pgfmathtruncatemacro\multiTableTempb{multiTableFunction(\multiTableRows,\multiTableTempa)},
    column #1/.append style/.expanded={every node/.append style={text width=width("\multiTableTempb")}}},
  multiplication table/.style={
    matrix of math nodes, nodes in empty cells,
    column sep=+-\pgflinewidth, row sep=+-\pgflinewidth,
    cells={nodes={outer sep=+0pt,
      if={(\pgfmatrixcurrentrow-1)*(\pgfmatrixcurrentcolumn-1)==0}{}{multiTable every node/.try}}},
    row 1/.style={nodes={
      if={\pgfmatrixcurrentcolumn==1}{}{node contents=\pgfmathprint{int(\pgfmatrixcurrentcolumn-1)}},
      multiTable first row/.try}},
    column 1/.style={nodes={
      if={\pgfmatrixcurrentrow==1}{}{node contents=\pgfmathprint{int(\pgfmatrixcurrentrow-1)}},
      multiTable first column/.try}},
    row 1 column 1/.append style={nodes={align=center,
      node contents={\cdot},multiTable tr/.try}},
    every cell/.append style={
      nodes={
        minimum size=+1.5em, draw, align=right,
        text height=+.7\baselineskip, text depth=+0\baselineskip,
        if={and(\pgfmatrixcurrentrow>1,\pgfmatrixcurrentcolumn>1)}{
          node contents={\pgfmathprint{multiTableFunction(\pgfmatrixcurrentrow-1,\pgfmatrixcurrentcolumn-1)}},
        }{}}}},
  multiTable first row/.style={fill=orange!50},
  multiTable first column/.style={fill=orange!50},
  multiTable tr/.style={fill=orange!20},
  multiTable def function/.style={multiTable set function={int(\r*\c)}},
  multiTable set function/.style={declare function={multiTableFunction(\r,\c)=#1;}}}
\newcommand*\addTo[2]{\expandafter\def\expandafter#1\expandafter{#1#2}}
\newcommand*\multiplicationTable[3][]{%
\begin{tikzpicture}[#1]
\pgfmathtruncatemacro\multiTableRows{#2}
\pgfmathtruncatemacro\multiTableColumns{#3}
\def\multiTableTempa{}
\pgfmathloop
  \addTo\multiTableTempa{\pgfmatrixnextcell}
  \ifnum\pgfmathcounter<\multiTableColumns
\repeatpgfmathloop
\addTo\multiTableTempa{\\}\let\multiTableSetupFinal\multiTableTempa
\pgfmathloop
  \expandafter\addTo\expandafter\multiTableSetupFinal\expandafter{\multiTableTempa}
  \ifnum\pgfmathcounter<\multiTableRows
\repeatpgfmathloop
\pgfmathtruncatemacro\multiTableTempb{\multiTableColumns+1}
\matrix[multiplication table,
  set column text width/.list={2,...,\multiTableTempb},
  column 1/.append style/.expanded={nodes={text width=width("\multiTableRows")}},
]{\multiTableSetupFinal};
\end{tikzpicture}}
\begin{document}
\multiplicationTable[
  multiTable def function,
  every cell/.append style={
    if={(abs(\pgfmatrixcurrentrow-\pgfmatrixcurrentcolumn)==6)}{nodes={fill=red!50}}{}},
  ]{10}{10}
\multiplicationTable[
  multiTable set function={int(\r^\c)},
  multiTable tr/.append style={node contents=r^c,fill=blue!20},
  column 2/.style={coordinate, column sep=+0pt},
  multiTable first row/.style={fill=blue!50},
  multiTable first column/.style={fill=blue!50},
  multiTable every node/.style={text=blue},% blue enough?
  ]{10}{4}
\end{document}

Output

enter image description here

enter image description here

Qrrbrbirlbel
  • 119,821
7

There is no need for PSTricks or TikZ, the good old environment picture will do:

\documentclass{article}
\usepackage{color} 

\newcounter{cntA}
\newcounter{cntB}
\newcommand*{\makerule}[2]{%
  \makebox(#1,#2){%
    \rule{#1\unitlength}{#2\unitlength}%
  }%
}

\begin{document}
  \noindent
  \mbox{%
    \setlength{\unitlength}{\linewidth}%
    \addtolength{\unitlength}{-.4pt}% half line width left and right
    \hspace{.2pt}%
    \begin{picture}(1, 1)
      \divide\unitlength by 12\relax
      % Draw background of header cells
      \textcolor{orange}{%
        \put(0, 0){\makerule{1}{12}}
        \put(0, 11){\makerule{12}{1}}
      }%
      % Set header cells
      \put(0, 11){\makebox(1, 1){$\times$}}
      \setcounter{cntA}{0}%
      \multiput(1, 11)(1, 0){11}{%
        \stepcounter{cntA}%
        \makebox(1, 1){\thecntA}%
      }
      \multiput(0, 0)(0, 1){11}{%
        \makebox(1, 1){\thecntA}%
        \addtocounter{cntA}{-1}%
      }
      % Color diagonals
      \textcolor{yellow}{%
        \multiput(1, 5)(1, -1){6}{\makerule{1}{1}}%
        \multiput(6, 10)(1, -1){6}{\makerule{1}{1}}%
      }%
      % Set body cells
      \setcounter{cntA}{0}%
      \multiput(1, 10)(0, -1){11}{%
        \stepcounter{cntA}%
        \setcounter{cntB}{0}%
        \multiput(0, 0)(1, 0){11}{%
          \stepcounter{cntB}%
          \makebox(1, 1){\the\numexpr\value{cntA}*\value{cntB}\relax}%
        }%
      }   
      % Draw lines
      \multiput(0, 0)(0, 1){13}{\line(1, 0){12}}
      \multiput(0, 0)(1, 0){13}{\line(0, 1){12}}
    \end{picture}%
    \hspace{.2pt}%
  }%
\end{document}

Result

Heiko Oberdiek
  • 271,626
6

A mixture of bits and pieces from various answers on this page and the OP's code...

\documentclass[pstricks,border=5]{standalone}    
\usepackage{expl3}
\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff    
\psset{dimen = m, fillstyle = solid}
\begin{document} 
\def\N{11}
\begin{pspicture}(\calc{\N+1},\calc{\N+1})
\psframe[fillcolor = orange](!0 \N\space 1 add)(1,\N)
\rput(!0.5 \N\space 0.5 add){$\cdot$}     
\foreach \i in {1,...,\N}{
  \psframe[fillcolor = orange](\i, \N)(\calc{\i+1}, \calc{\N+1})
  \rput(\calc{\i+.5}, \calc{\N+.5}){$\i$}
  \psframe[fillcolor = orange](0, \calc{\N-\i})(1, \calc{\N-\i+1})
  \rput(0.5, \calc{\N-\i+.5}){$\i$}
}     
\foreach \iA in {1,...,\N}{\foreach \iB in {1,...,\N}{
    \edef\x{\calc{abs(\iA-\iB)}} 
    \ifnum\x=5
      \colorlet{fill color}{blue!20}
    \else
      \colorlet{fill color}{white}
    \fi
    \psframe[fillcolor=fill color](\iA, \calc{\N-\iB})(\calc{\iA+1}, \calc{\N-\iB+1})
    \rput(\calc{\iA+.5}, \calc{\N-\iB+.5}){$\calc{\iA*\iB}$} 
}}
\end{pspicture}    
\end{document}

enter image description here

Mark Wibrow
  • 70,437
5

MetaPost is another adequate candidate for this kind of pictures.

input mpcolornames; color myorange; myorange = .5[Red,Yellow];
input latexmp; setupLaTeXMP(mode = rerun, textextlabel = enable);
u := 1cm;
def loc(expr i,j) = 
  ((i-.5, -.5-j) -- (i+.5, -.5-j) -- (i+.5, .5-j) -- (i-.5, .5-j) -- cycle) scaled u
enddef;
beginfig(1);
  fill loc(0, 0) withcolor myorange; label(".", origin); 
  for i = 1 upto 11:
    fill loc(i, 0) withcolor myorange;
    label(decimal i, (i*u, 0));
    fill loc(0, i) withcolor myorange;
    label(decimal i, (0, -i*u));
  endfor
  % Filling
  for i = 1 upto 11:
    for j = 1 upto 11:
      if abs(i-j) = 5: fill loc(i,j) withcolor Yellow; fi
      label(decimal(i*j), u*(i, -j));
    endfor
  endfor
  % Grid lines
  for i = 0 upto 12:
    draw u*(i-0.5, .5) -- u*(i-0.5, -11.5);
    draw u*(-0.5, 0.5-i) -- u*(11.5, 0.5-i);
  endfor;
endfig;
end.

For each pair (i,j) of integers, the macro loc(i,j) gives its location in the table (the square which contains i*j, in this order), and the following instruction fills this location with yellow color if |i-j|=5:

if abs(i-j) = 5: fill loc(i,j) withcolor Yellow; fi

Result:

enter image description here

Franck Pastor
  • 18,756