25

I'm finding this extraordinarily difficult to search for, as the mathematical meaning of "array" is much more common in LaTeX documentation. I essentially want a single row of boxes, into which I can put numbers, strings, etc. Can someone point me in the right direction?

Edit:

enter image description here

The picture above is an example of the sort of thing I am looking for (it doesn't have to be exactly like this).

5
  • Can you show us an example?
    – topskip
    Oct 12, 2011 at 14:07
  • @Patrick: see my edit.
    – Matthew
    Oct 12, 2011 at 14:11
  • TikZ would be overkill. But... I almost can't resist. I'll leave it a while first.
    – Seamus
    Oct 12, 2011 at 14:14
  • Such brackets can be done with mathtools' \underbracket.
    – N.N.
    Oct 12, 2011 at 14:22
  • @N.N. The brackets would be nice, but it is more the boxes that I am worried about.
    – Matthew
    Oct 12, 2011 at 14:26

4 Answers 4

27

The most straightforward way of putting something in a framed box is the \fbox command.

\documentclass{article}
\begin{document}
  \newcommand{\sep}{\hspace*{.5em}}
  \noindent
  $\fbox{5} \sep \fbox{2} \sep \fbox{7} \sep \fbox{-5} \sep \fbox{16} \sep \fbox{12}$
\end{document}

fboxed entries

Now that does not look very nice, the boxes are differently sized, depending on what is inside of them. To solve this we would need additional macros to determine the longest number in the input, etc.

It's probably better to use Tikz:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
  \begin{tikzpicture}
    \coordinate (s) at (0,0);
    \foreach \num in {5,2,7,-5,16,12}{
      \node[minimum size=6mm, draw, rectangle] at (s) {\num};
      \coordinate (s) at ($(s) + (1,0)$);
    }
  \end{tikzpicture}
\end{document}

enter image description here

These boxes look a lot nicer, furthermore it also provides you with options for the shading and the brackets you have in your example. Have a look at the manual, Tikz can do pretty much anything.

For the sake of completion, I will add some code to get something close to the picture you gave as an example in the question.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\newcounter{nodeidx}
\setcounter{nodeidx}{1}
\newcommand{\nodes}[1]{%
    \foreach \num in {#1}{
      \node[minimum size=6mm, draw, rectangle] (\arabic{nodeidx}) at (\arabic{nodeidx},0) {\num};
      \stepcounter{nodeidx}
    }
}
\newcommand{\brckt}[4]{% from, to, lvl, text
  \draw (#1.south west) ++($(-.1, -.1) + (-.1*#3, 0)$) -- ++($(0,-.1) + (0,-#3*1.25em)$) -- node [below] {#4} ($(#2.south east) + (.1,-.1) + (.1*#3, 0) + (0,-.1) + (0,-#3*1.25em)$) -- ++($(0,#3*1.25em) + (0,.1)$);%
}
\begin{document}
  \begin{tikzpicture}
    \pgftransparencygroup
    \nodes{5,2,7,-5,16,12}
    \endpgftransparencygroup
    \pgfsetstrokeopacity{0.5}
    \pgfsetfillopacity{0.5}
    \pgftransparencygroup
    \nodes{?,?,?,?,?,?}
    \endpgftransparencygroup
    \pgfsetstrokeopacity{.75}
    \pgfsetfillopacity{.75}
    \pgftransparencygroup
    \brckt{1}{6}{0}{size=6}
    \endpgftransparencygroup
    \pgfsetfillopacity{0.5}
    \pgfsetstrokeopacity{0}
    \pgftransparencygroup
    \brckt{7}{12}{0}{free space}
    \endpgftransparencygroup
    \pgfsetstrokeopacity{0.5}
    \pgftransparencygroup
    \brckt{1}{12}{1}{capacity=12}
    \endpgftransparencygroup
  \end{tikzpicture}
\end{document}

This provides a \nodes command that takes a list of array values and creates boxes accordingly. The counter is used here to make labelling a little easier than with the updated coordinate. Note that you should reset the counter when you want to create a new array. The \brckt command allows for a bracket to be drawn and takes as an argument the index from, the index to, the level and the text to be put on the bracket. The level is used to determine how far from the nodes the bracket should be drawn. The use of the transparency groups is due to some strange issues I got, couldn't figure out what was happening exactly, so just wrapped everything up in a group to make it work. If some one knows why the groups are needed, please add it and let me know?

The final result looks like this: Full example using Tikz

Fixing the spacing and bracket placement to match the example exactly is left as a (not too difficult) exercise to the reader.

3
  • Ah, this is exactly the sort of thing I was looking for. I wrapped your Tikz sample in a \newcommand that takes the list of elements as a parameter, and it works perfectly. Thanks!
    – Matthew
    Oct 12, 2011 at 15:00
  • @wh1t3: What do you mean "strange issues"? I'm not a tikz expert, but grouping in LaTeX provides scope within which the contents usually acts locally. It may be that the transparency is compounded if you don't use it.
    – Werner
    Oct 13, 2011 at 15:40
  • @Werner: The issue I was having is that if the groups are removed the free space bracket is drawn. I can't imagine it is a compounding issue, since the opacity is set to 0 before drawing the bracket and then to 0.5 afterwards, yet the 0.5 opacity is used on the bracket. It looks like the commands aren't executed in order for some reason. Kind of stumped me. Oct 14, 2011 at 12:36
18

Here is a sans-tikz approach to typesetting an array. The etoolbox package provides \docsvlist that processes a comma separated value (CSV) list using the element-wise generic \do command that takes one argument. By redefining \do, you can modify the operation performed on/to each element.

In the following minimal working example, the \printarray[<width>]{<csv list>} typesets <csv list> as an array. The command scans the list first in order to establish the number of elements in the list. Then, during the second parse, it typesets each element using the standard \framebox. The optional parameters allow for modifying the width of the contents of each box (default is fixed at 1em).

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\usepackage{mathtools}% http://ctan.org/pkg/mathtools
\usepackage{xcolor}% http://ctan.org/pkg/xcolor
\begin{document}

\newcounter{listcount} \newcounter{totcount}
%\setlength{\fboxsep}{0.5pt}%

\newcommand{\printarray}[2][1em]{% \printarray[<width>]{<array list>}
  \unskip \setcounter{totcount}{0}% Reset totcount counter
  \renewcommand*{\do}[1]{\stepcounter{totcount}}% Count elements
  \docsvlist{#2}% Process list a first time to obtain # of elements
  \setcounter{listcount}{0}% Reset listcount counter
  \renewcommand*{\do}[1]{%
    \stepcounter{listcount}% Move to next element
    \framebox[#1][c]{\rule{0pt}{1.5ex}\smash{\ensuremath{##1}}}%
    \ifnum\value{listcount}<\value{totcount}\thickspace\fi
  }
  \docsvlist{#2}% Process list a second time to typeset each element
}

The array \printarray{1,2,3,4} is really trivial. However, \printarray[2em]{1,-3,2,16} is not. Also%
\[
  \color{black!50}%
  \underbracket[0.5pt]{{\thickspace}%
    \underbracket[0.5pt][5pt]{{\thickspace}%
      \color{black}\printarray[2em]{5,2,7,-5,16,12}\thickspace}_{\textrm{size}=6}\negthickspace%
    \color{black!25}\underbracket[0pt][5.5pt]{{\thickspace}%
      \printarray[2em]{?,?,?,?,?,?}\thickspace}_{\textrm{free~space}}%
  \thickspace}_{\textrm{capacity}=12}
\]

\end{document}

Printing an array

\underbracket[<thickness>][<height>]{<arg>} is provided by mathtools, while colour shading is offered by xcolor. Modifying the length \fboxsep (remove the commented \setlength command) changes the gap between the framed box and it's contents. For visual aesthetics, the contents of the framed box is \smashed to a fixed height of 1.5ex.

5

I like the idea of not using Tikz to typeset this kind of thing, since it might be a little bit over the top for something this simple. We don't need to use external packages though, since tex can already handle comma separated lists quite well. We can also easily add some code to deal with the width of the boxes. That would look like this:

\documentclass{article}
\makeatletter
\let\dotlessi\i
\newlength{\longest} 
\newlength{\@temp}
\newlength{\sep}
\setlength{\sep}{5pt}
\newcommand{\findlongest}[1]{%
  \setlength{\longest}{0pt}%
  \@for\i:=#1\do{%
    \settowidth{\@temp}{\ensuremath{\i}}%
    \ifdim\longest<\@temp%
      \setlength{\longest}{\@temp}%
    \fi
  }
}
\newcommand{\printarray}[1]{%
  \ifx#1\empty\else
    \findlongest{#1}%
    \addtolength{\longest}{2\sep}%
    \@for\i:=#1\do{%
      \framebox[\longest]{\rule{0pt}{1.5ex}\smash{\ensuremath{\i}}}\hskip2\sep%
    }%
    \hskip-2\sep% remove final skip
    \ %add space
  \fi
}
\let\i\dotlessi
\makeatother
\begin{document}
  \printarray{5,2,7,-5,16,12,?,?,?,?,?,?}
\end{document}

\findlongest is a helper method that finds the widest element of a list and sets the length \longest to this width. \printarray then just puts everything in a box smashed to 1.5ex high and \longest wide.

The final result looks like this: typeset array

4

I'm a bit late to the party, hope you don't mind (in plain-tex):

\newdimen\boxitspace\boxitspace=3pt% boxit from eplain
\long\def\boxit#1{\vbox{\hrule\hbox{\vrule\kern\boxitspace\vbox{%
  \kern\boxitspace\parindent0pt#1\kern\boxitspace}%
  \kern\boxitspace\vrule}\hrule}}
\def\aryitem#1{\boxit{\hbox to 1.4em{\hfil#1\hfil}}}% change 1.4em if needed
\let\MS\multispan% shorten a little
\halign{&\thinspace\aryitem{$\mathstrut#$}\thinspace\cr
  5&2&7&-5&16&12&\omit\quad&?&?&?&?&?&?\cr
  \MS6\upbracefill&\omit&\MS6\upbracefill\cr
  \MS6\hfill size $=6$\hfill&\omit&\MS6\hfill free space\hfill\cr
  \MS{13}\upbracefill\cr
  \MS{13}\hfill capacity $=12$\hfill\cr
}
\bye

which looks like
ary

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .