EDIT: Added LuaTeX version
Probably not what is exactly wanted. Also somewhat crude, and slow. Using LuaTeX
or PSTricks
would be very good choice to speed this up. But I'm old fashioned and stuck in my ways, so...
\documentclass[tikz]{standalone}
\usepackage{tikz}
% Each cell is stored globally as a macro
% for example \csname cell-glider-1-7\endcsname
\def\setcell#1#2#3{%
\pgfmathparse{int(#2)}\let\cx=\pgfmathresult%
\pgfmathparse{int(#3)}\let\cy=\pgfmathresult%
\expandafter\xdef\csname cell-#1-\cx-\cy\endcsname%
}
% Cells are accessed by parsing #2 and #3 to integers
% and assigning the cell contents to the macro #4
\def\getcell#1#2#3#4{%
\pgfmathparse{int(#2)}\let\cx=\pgfmathresult%
\pgfmathparse{int(#3)}\let\cy=\pgfmathresult%
\def\marshal{\xdef#4}%
\marshal{\csname cell-#1-\cx-\cy\endcsname}%
}
% We flip the current from `current' to `next'
% which is probably misleading. The texts can be
% any arbitrary string as long as they are different.
\def\currenttext{current}
\def\nexttext{next}
\let\currentgeneration=\currenttext
\let\nextgeneration=\nexttext
\def\switchgenerations{%
\ifx\currentgeneration\currenttext%
\global\let\currentgeneration=\nexttext%
\global\let\nextgeneration=\currenttext%
\else%
\global\let\currentgeneration=\currenttext%
\global\let\nextgeneration=\nexttext%
\fi%
}
% Define colors \csname color-#1\endcsname
% Which can be used according to the cell contents
% So \csname color-0\endcsname holds the color for cells with value 0
\def\setcolor#1{\expandafter\xdef\csname color-#1\endcsname}
\def\getcolor#1{\csname color-#1\endcsname}
% Define a 10x10 board with a border of 1 so edge
% detection is not necessary.
\foreach \x in {0,...,11}{%
\foreach \y in {0,...,11}{%
\setcell{\currentgeneration}{\x}{\y}{0}%
}% %
}%
% Copy this board for the next generation
% This is HUGELY inefficient. What would be better is
% to maintain a list of only changing cells (hard in LaTeX)
\foreach \x in {0,...,11}{%
\foreach \y in {0,...,11}{%
\setcell{\nextgeneration}{\x}{\y}{0}%
}%
}
\newcount\neighbors
\def\updategenerations{%
\begingroup\nullfont% Hmm lots of unwanted spaces occur here
\foreach \x in {1,...,10}{%
\foreach \y in {1,...,10}{%
\getcell{\currentgeneration}{\x}{\y}{\n}%
\getcell{\currentgeneration}{\x-1}{\y}{\a}%
\getcell{\currentgeneration}{\x+1}{\y}{\b}%
\getcell{\currentgeneration}{\x}{\y-1}{\c}%
\getcell{\currentgeneration}{\x}{\y+1}{\d}%
\getcell{\currentgeneration}{\x-1}{\y-1}{\e}%
\getcell{\currentgeneration}{\x+1}{\y-1}{\f}
\getcell{\currentgeneration}{\x-1}{\y+1}{\g}%
\getcell{\currentgeneration}{\x+1}{\y+1}{\h}%
\pgfmathsetcount\neighbors{\a+\b+\c+\d+\e+\f+\g+\h}%
% Here are the neighbor rules
\ifcase\neighbors %
\setcell{\nextgeneration}{\x}{\y}{0}% 0 neighbors
\or
\setcell{\nextgeneration}{\x}{\y}{0}% 1 neighbors
\or
\ifnum\n=1\relax
\setcell{\nextgeneration}{\x}{\y}{1}% 2 neighbors
\fi
\or
\setcell{\nextgeneration}{\x}{\y}{1}% 3 neighbors
\else
\setcell{\nextgeneration}{\x}{\y}{0}% more than 3 neighbors
\fi%
}%
}%
\endgroup%
\switchgenerations%
}
\def\drawcurrentgeneration{%}
\begin{tikzpicture}[x=10pt,y=10pt]
\foreach \x in {1,...,10}{%
\foreach \y in {1,...,10}{%
\setcell{\nextgeneration}{\x}{\y}{0}% Do here for a *minor* increment in speed
\getcell{\currentgeneration}{\x}{\y}{\value}%
\edef\c{\getcolor{\value}}%
\fill [fill=\c](\x, \y) rectangle ++(1,1);
}
}
\end{tikzpicture}%
}
\setcolor{0}{blue!5}
\setcolor{1}{blue!20}
\setcell{\currentgeneration}{1}{8}{1}
\setcell{\currentgeneration}{2}{8}{1}
\setcell{\currentgeneration}{3}{8}{1}
\setcell{\currentgeneration}{3}{9}{1}
\setcell{\currentgeneration}{2}{10}{1}
\begin{document}
\drawcurrentgeneration
\foreach \iteration in {1,...,28}{
\updategenerations
\drawcurrentgeneration
}
\end{document}
And here's how it could be done in LuaTeX
:
\documentclass[tikz]{standalone}
\usepackage{tikz}
\directlua{
function declareCells(n)
MNew = {}
for i = 0, n+1 do
MNew[i] = {}
for j = 0, n+1 do
MNew[i][j] = 0
end
end
return MNew
end
function upDateCells(M, n)
MNew = declareCells(n)
for i = 1, n do
for j = 1, n do
nb = - M[i][j]
for ni = -1, 1 do
for nj = -1, 1 do
nb = nb + M[i+ni][j+nj]
end
end
if nb < 2 then
MNew[i][j] = 0
elseif nb < 4 then
if M[i][j] == 1 then
MNew[i][j] = 1
elseif nb == 3 then
MNew[i][j] = 1
end
else
MNew[i][j] = 0
end
end
end
return MNew
end
}
\def\declarecells#1#2{
\directlua{
#1=declareCells(#2)
#1size=#2
}}
\def\updatecells#1{
\directlua{
#1 = upDateCells(#1, #1size)
}}
\def\getcell#1#2#3#4{%
\edef#4{\directlua{tex.print(#1[#2][#3])}}%
}
\def\setcell#1#2#3#4{%
\directlua{#1[#2][#3]=#4}%
}
\def\setcolor#1{\expandafter\xdef\csname color-#1\endcsname}
\def\getcolor#1{\csname color-#1\endcsname}
\setcolor{0}{blue!5}
\setcolor{1}{blue!20}
\def\drawcells#1{%
\edef\n{\directlua{tex.print(#1size)}}
\begin{tikzpicture}[x=10pt,y=10pt]
\foreach \x in {1,...,\n}{%
\foreach \y in {1,...,\n}{%
\getcell{#1}{\x}{\y}{\value}%
\edef\c{\getcolor{\value}}%
\fill [fill=\c](\x, \y) rectangle ++(1,1);
}
}
\end{tikzpicture}%
}
\begin{document}
\declarecells{glider}{10}
\setcell{glider}{1}{8}{1}
\setcell{glider}{2}{8}{1}
\setcell{glider}{3}{8}{1}
\setcell{glider}{3}{9}{1}
\setcell{glider}{2}{10}{1}
\drawcells{glider}
\foreach \iteration in {1,...,28}{
\updatecells{glider}
\drawcells{glider}
}
\end{document}
The result is the same as before.
dimensions are not stored with a unit (actually they are always stored as an integer, in sp
units). Whatever unit is used when setting the length (if a unit is used at all) \the
will show the length using pt
units.
Settings that don't use any explicit unit include things like
\setbox0\hbox{abc} \dimen0=\wd0
Best Answer
You can use
node
and control its dimensions.Here
\vphantom
adds the total height (i.e., height ofS
and depth ofg
)PS
\fbox
is there just to show the heights.