diff options
author | Karl Berry <karl@freefriends.org> | 2010-05-05 23:00:12 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2010-05-05 23:00:12 +0000 |
commit | 01421ee8d5eea8634737b0c96ca01ea93fefeb41 (patch) | |
tree | 92f1aa13153fe84d8e6b2d18626f86da06e8e14f | |
parent | e5875f3cea3bcfc703ea0a5dce87c986ccaeb008 (diff) |
oops
git-svn-id: svn://tug.org/texlive/trunk@18117 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/tex/generic/arrayjobx/README | 29 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/arrayjobx/arrayjob.pdf | bin | 463847 -> 0 bytes | |||
-rw-r--r-- | Master/texmf-dist/tex/generic/arrayjobx/arrayjob.sty | 188 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/arrayjobx/arrayjob.tex | 2097 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.pdf | bin | 464034 -> 0 bytes | |||
-rw-r--r-- | Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.tex | 2096 |
6 files changed, 0 insertions, 4410 deletions
diff --git a/Master/texmf-dist/tex/generic/arrayjobx/README b/Master/texmf-dist/tex/generic/arrayjobx/README deleted file mode 100644 index e8db2aec6f4..00000000000 --- a/Master/texmf-dist/tex/generic/arrayjobx/README +++ /dev/null @@ -1,29 +0,0 @@ - +-----------------------------------------------------------+ - | 'arrayjob'; 'arrayjobx' | - | Versions 1.03; 1.04 | - | May 3, 2000; May 3, 2010 | - | | - | Zhuhan Jiang (University of Western Sydney - Australia) | - | <zhuhan@scm.uws.edu.au> | - +-----------------------------------------------------------+ - - -The 'arrayjob(x)' package provides array data structures in (La)TeX, in the -meaning of the classical procedural programming languages like Fortran, Ada or -C, and macros to manipulate them. Arrays can be mono or bi-dimensional. - -This is useful for applications which require high level programming -techniques, like algorithmic graphics programmed in the TeX language. - -The accompanying documentation files (arrayjob.tex, arrayjobx.tex ) were -written by Denis Girou <Denis.Girou@idris.fr> and updated by Michael Sharpe -(msharpe@ucsd.edu). - -Version 1.03 (arrayjob) is provided only for compatibility with old work that -made explicit use of the \array macro. Version 1.04 (arrayjobx, modification -suggested by Michael Sharpe) should be used for all new work---the only -difference is that the macro known as \array in version 1.03 is known under -the name \arrayx in version 1.04 in order to avoid conflict with the name -\array as used in amsmath. - -This package is released under the terms of the LaTeX Project Public License. diff --git a/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.pdf b/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.pdf Binary files differdeleted file mode 100644 index a20bf9e175d..00000000000 --- a/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.pdf +++ /dev/null diff --git a/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.sty b/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.sty deleted file mode 100644 index 0712a49d114..00000000000 --- a/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.sty +++ /dev/null @@ -1,188 +0,0 @@ -% ARRAY STRUCTURE - arrayjob.sty - Version 1.03 - 05/03/00 -% -% By Zhuhan Jiang (01/05/95), extracted from formlett.sty -% (see CTAN/macros/generic/formlett.sty from line 344 to line 483) -% -% This program can be redistributed and/or modified under the terms -% of the LaTeX Project Public License distributed from CTAN archives -% in directory macros/latex/base/lppl.txt -% -% * 01/05/95 - Version 1.00 -% + Original version -% * 12/21/99 - Version 1.01 -% + Spurious blanks removed in \read@array and \get@max@count -% (reported by Antonio Leitao <aml@gia.ist.utl.pt> -% and Denis Girou <Denis.Girou@idris.fr>) -% * 04/05/00 - Version 1.02 -% + Add the \ifexpandarrayelement macro to allow to evaluate -% or not the content to put as an element of the array -% (from Denis Girou <Denis.Girou@idris.fr>) -% + Put this package under the terms of the LaTeX Project -% Public License -% * 05/03/00 - Version 1.03 -% + Add a \ProvidesPackage macro when LaTeX is used -% (according to the example given by Bernd Raichle -% <raichle@Informatik.Uni-Stuttgart.DE>) -% -% -% \newarray\ARRAYNAME -% \delarray\ARRAYNAME -% -% \ARRAYNAME(A1,..,An)={T} -% \readarray{ARRAYNAME}{ B1 & B2 & ... & Bm } -% \dataheight -% -% \data(A1,...,An)=\data( A1 + (A2-1)*\dataheight + -% ... + (An-1)*\dataheight^{n-1} ) -% if \normalindextrue -% =\data( An + (An-1 -1)*\dataheight + -% ... + (A1-1)*\dataheight^{n-1} ) -% if \normalindexfalse -% -% \checkARRAYNAME(A1,..,An) -% \ifemptydata valid when \checkARRAYNAME is just executed -% \cachedata: keeps the data of \ARRAYNAME(m) -% when \checkARRAYNAME(m) is executed -% -% OTHERS: -% save to array: \array{n}(m)={T} -% get from array: \array{n}(m) -% clear element: \clrarray{n}(m) -% test element: \testarray{n}(m) -% macro save to \temp@macro -% -% -% e.g. -% -% \newarray\Table -% \readarray{Table}{one&two& \unknownmacro && &six} -% \Table(7)={seven} -% \dataheight=0 % or 1 or < 0 -% \Table(7) = \Table(2,6,1) % 7=1+(2-1)+(6-1)+(1-1) -% \normalindexfalse -% \dataheight=3 -% \Table(7) = \Table(1,7) = \Table(3,1) -% \normalindextrue -% \Table(7) = \Table(7,1) = \Table(1,3) -% -% \checkTable(4) \ifemptydata (4)=empty \fi -% \checkTable(5) \ifemptydata\else (5)=nonempty \fi -% \ifx\cachedata\space ={\tt <space>}\fi -% \checkTable(1000) \ifemptydata (1000)=empty \fi -% -% \delarray\Table -% -% -\begingroup\expandafter\expandafter\expandafter\endgroup -\expandafter\ifx\csname ProvidesPackage\endcsname\relax% -\else - \ProvidesPackage{arrayjob}[2000/05/03 v1.03 Array management] -\fi -% -\xdef\EntryArrayJob{\the\catcode`\@}\catcode`\@=11\relax -\newif\ifemptydata \newcount\dataheight -\newif\ifnormalindex \normalindexfalse -% -\newcount\array@width \newcount\index@count \newcount\index@total -\newif\ifone@VEC \newif\if@rev@index -\newtoks\temp@toks \newcount\temp@count -\newcount\temp@@count \newcount\temp@@@count -% -\newif\ifexpandarrayelement -% -\long\def\assign@VEC#1(#2)=#3{\temp@count=#2 \relax -\get@max@count{total@#1}\temp@count -\ifexpandarrayelement - \expandafter\xdef\csname#1#2\string~\endcsname{#3}% -\else - \expandafter\gdef\csname#1#2\string~\endcsname{#3}% -\fi} -\def\get@VEC#1(#2){\csname#1#2\string~\endcsname} -\def\clrarray#1(#2){% - \global\expandafter\let\csname#1#2\string~\endcsname=\undefined@} -% -\def\testarray#1(#2){% - \expandafter\let\expandafter\temp@macro\csname#1#2\string~\endcsname - \ifx\temp@macro\relax \def\temp@macro{}\fi}% -% -\def\array#1(#2){\def\check@VEC{% - \ifx=\next@VEC \def\full@VEC####1{\assign@VEC#1(#2)####1}% - \else \def\full@VEC{\get@VEC#1(#2)}\fi \full@VEC}%check@VEC -\futurelet\next@VEC\check@VEC} -% -\def\get@index(#1)#2\safty@mark{\one@VEC#2,\safty@mark - \def\next@@VEC{#1}\ifx\next@@VEC\empty\def\next@@VEC{\array@width}\fi - \if@rev@index - {\temp@count=1 \advance\index@count1 \relax - \ifnum\index@count<\index@total - \loop \multiply\temp@count \next@@VEC - \advance\index@count-1 \relax - \ifnum\index@count>0 \repeat - \fi \global\temp@@count\temp@count }% - \else \multiply\temp@@count \next@@VEC \fi - \ifnum\temp@@count=0 \temp@@count=1 \relax \fi - \advance\temp@count-1 \ifnum\temp@count<0 \temp@count=0 \fi - \multiply\temp@count \temp@@count - \advance\temp@@@count by \temp@count \advance\index@count1 - \ifone@VEC - \def\next@@VEC{\index@total=\index@count \advance\temp@@@count1 }% - \else \one@VEC#2\safty@mark \edef\next@@VEC{\noexpand\get@index(#1)% - \the\temp@toks\noexpand\safty@mark}% - \fi \next@@VEC}% -% -\def\one@VEC#1,#2\safty@mark{\def\temp@macro{#2}\temp@toks={#2}% - \ifx\temp@macro\empty \one@VECtrue \else \one@VECfalse \fi - \temp@count=#1 \relax }% -% -\def\get@all@index(#1)#2\safty@mark{% - \temp@@@count=0 \temp@@count=0 \index@count=0 \@rev@indexfalse - \get@index(#1)#2\safty@mark - \ifnormalindex\else - \temp@@@count=0 \temp@@count=0 \index@count=0 \@rev@indextrue - \get@index(#1)#2\safty@mark \fi }% -% -\def\read@array[#1]#2#3{\temp@count=1 - \def\one@item##1#1##2\safty@mark{\def\temp@macro{##2}\temp@toks={##2}% - \ifx\temp@macro\empty\else - \def\temp@macro{\one@item##2\safty@mark}\fi - {\temp@toks={##1}\def\temp@@macro{\array{#2}(\the\temp@count)=}% - \expandafter\temp@@macro\expandafter{\the\temp@toks}}% - \expandafter\edef\csname total@#2\endcsname{\the\temp@count}% - \advance\temp@count1\temp@macro}% - \one@item#3#1\safty@mark}% -% -\def\strip@esc#1{\temp@count=\escapechar \escapechar=-1 % - \temp@toks=\expandafter{\string#1}\escapechar\temp@count} -\def\get@max@count#1#2{\edef\temp@macro{\csname #1\endcsname}% - \ifnum\temp@macro<#2\expandafter\xdef\csname #1\endcsname{\the#2}\fi}% -% -\def\newarray#1{\strip@esc{#1}% - \expandafter\gdef\csname total@\the\temp@toks\endcsname{0}% - \expandafter\edef\csname\the\temp@toks\endcsname(##1)% - {\noexpand\get@all@index(\noexpand\dataheight)##1\noexpand\safty@mark -% \noexpand\get@max@count{total@\the\temp@toks}\noexpand\temp@@@count - \noexpand\array{\the\temp@toks}(\noexpand\the\noexpand\temp@@@count)}% - \expandafter\edef\csname check\the\temp@toks\endcsname(##1)% - {\noexpand\get@all@index(\noexpand\dataheight)##1\noexpand\safty@mark - \noexpand\testarray{\the\temp@toks}(\noexpand\the - \noexpand\temp@@@count)\noexpand\let\noexpand\cachedata - \noexpand\temp@macro\noexpand\ifx\noexpand\temp@macro\noexpand\empty - \noexpand\emptydatatrue\noexpand\else\noexpand\emptydatafalse - \noexpand\fi}}% -% -\def\delarray#1{\strip@esc{#1}% delete array globally - \temp@count=0 \temp@@count=\csname total@\the\temp@toks\endcsname - \loop \expandafter\global\expandafter\let - \csname\the\temp@toks\string~\endcsname\undefined@ - \advance\temp@count1 % - \ifnum\temp@count<\temp@@count \repeat % global loop for less memory - \global\expandafter\let\csname total@\the\temp@toks\endcsname\undefined@ - \global\expandafter\let\csname \the\temp@toks\endcsname\undefined@ - \global\expandafter\let\csname check\the\temp@toks\endcsname\undefined@ }% -% -\def\readarray#1#2{\read@array[&]{#1}{#2}}% -% -\catcode`\@=\EntryArrayJob\relax -\endinput -% -% END OF MACROS diff --git a/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.tex b/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.tex deleted file mode 100644 index 899cfe39e7e..00000000000 --- a/Master/texmf-dist/tex/generic/arrayjobx/arrayjob.tex +++ /dev/null @@ -1,2097 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% arrayjob.doc --- Documentation of the `arrayjob' package from Zhuhan Jiang -%% -%% Author : Denis GIROU (CNRS/IDRIS - France) <Denis.Girou@idris.fr> -%% Created the : Fri Jan 7 21:13:20 2000 -%% Last mod. by : Denis GIROU (CNRS/IDRIS - France) <Denis.Girou@idris.fr> -%% Last mod. the : Wed May 31 20:10:39 2000 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\documentclass{article} - -\usepackage{arrayjob} % Arrays management -\usepackage{fancyvrb} % Fancy verbatims -\usepackage[width=18cm]{geometry} % Page layout -\usepackage{graphics} % Graphics LaTeX standard package -\usepackage{ifthen} % Convenient conditionals in LaTeX -\usepackage{mflogo} % For the MetaFont and MetaPost logos -\usepackage{multido} % General loop macro -\usepackage{url} % URLs convenient typesetting -\usepackage{trace} - -% For PSTricks examples -\newif\ifpstricks -\IfFileExists{pstricks.sty}{% -\pstrickstrue -%\usepackage{pstcol} % PSTricks package with `color' interface -\usepackage{pst-node} % PSTricks nodes package -\usepackage{pst-plot} % PSTricks plots package -\usepackage{pst-grad} % PSTricks gradients package -%\usepackage{pst-key} % PSTricks interface to the `keyval' package -}{% -\usepackage{color} -} % Color LaTeX standard package - -% Definition of new colors -\definecolor{Khaki} {rgb}{0.94,0.90,0.55} -\definecolor{LemonChiffon}{rgb}{1.,0.98,0.8} - -% A unique string for TeX and LaTeX -\newcommand{\AllTeX}{% -{\rm(L\kern-.36em\raise.3ex\hbox{\sc a}\kern-.15em)% -T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}} - -% Package names -\newcommand{\AlDraTeXPackage}{\textsf{(Al)Dra\TeX}} -\newcommand{\ArrayJobPackage}{`\textsf{arrayjob}'} -\newcommand{\FormLettPackage}{`\textsf{formlett}'} -\newcommand{\IfThenPackage}{`\textsf{ifthen}'} -\newcommand{\MetaFontPackage}{\MF} -\newcommand{\MetaPostPackage}{\MP} -\newcommand{\MultiDoPackage}{`\textsf{multido}'} -\newcommand{\PSTricksPackage}{\textsf{PSTricks}} -\newcommand{\RepeatPackage}{`\textsf{repeat}'} - -% Aligned labels in a description environment -\newenvironment{Description}[1]{% -\begin{list}{nothing}{\setlength{\leftmargin}{#1} -\setlength{\labelwidth}{\leftmargin}\setlength{\labelsep}{1mm}}} -{\end{list}} - -% If PSTricks is not available -\newcommand{\PSTricksExampleNotShown}{% -\vspace{2mm} -\centerline{\fbox{\textbf{Example not shown here because PSTricks is not - available on this platform.}}}} - -% Character to define verbatim strings, with escape characters /?; (from `fancyvrb') -\DefineShortVerb[commandchars=/?;]{\!} - -\VerbatimFootnotes % Allow verbatim material in footnotes (from `fancyvrb') - -% Some advices from Rolf Niepraschk -\newcommand{\BS}{\texttt{\symbol{`\\}}} -\newcommand{\Macro}[1]{\texttt{\BS#1}} -\newcommand{\Variable}[1]{\textnormal{\textit{\(\langle\)#1\,\(\rangle\)}}} -\newcommand{\Parameter}[1]{\texttt{\symbol{`\{}#1\symbol{`\}}}} - -% To format TeX macro strings -\newcommand{\FormatTeXMacro}[1]{\Macro{#1}\hfill :} - -\makeatletter - -% Example environments -% (do not use in them the /?; characters, that we will be used as escape characters!) - -% For highlighting some verbatim sequences (array names, macro names and comments) -\def\HLReverse#1{{% -\setlength{\fboxsep}{1pt}% -\colorbox{black}{\textcolor{white}{\textbf{#1}}}}} -\def\HLMacro#1{\BS{}def\HLMacro@i#1\@nil} -\def\HLMacro@i#1def#2\@nil{{% -\setlength{\fboxsep}{1pt}% -\colorbox{black}{\textcolor{white}{\textbf{#2}}}}} -\def\HLComment#1{\textit{#1}} - -\def\Example{\FV@Environment{}{Example}} -\def\endExample{% -\end{VerbatimOut} -\Below@Example{\input{\jobname.tmp}} -\endgroup} - -\def\CenterExample{\FV@Environment{}{Example}} -\def\endCenterExample{% -\end{VerbatimOut}% -\begin{center} -\Below@Example{\input{\jobname.tmp}} -\end{center} -\endgroup} - -\def\SideBySideExample{\FV@Environment{}{Example}} -\def\endSideBySideExample{% -\end{VerbatimOut}% -\SideBySide@Example{\input{\jobname.tmp}} -\endgroup} - -\def\FVB@Example{% -\begingroup -\FV@UseKeyValues -\parindent=0pt -\multiply\topsep by 2 -\VerbatimEnvironment -\begin{VerbatimOut}[codes={\catcode`\Z=12}]{\jobname.tmp}} - -\def\Below@Example#1{% -\VerbatimInput[gobble=0,commentchar=Z,commandchars=/?;,numbersep=3pt, - frame=single,numbers=left]% - {\jobname.tmp} -\catcode`\Z=9\relax% -% We suppress the effect of the highlighting macros -\catcode`/=0\relax% -\catcode`?=1\relax% -\catcode`;=2\relax% -\def\HLReverse##1{##1}% -\def\HLMacro##1{##1}% -\def\HLComment##1{##1}% -#1\par} - -\def\SideBySide@Example#1{% -\@tempdimb=\FV@XRightMargin -\advance\@tempdimb -5mm -\begin{minipage}[c]{\@tempdimb} - \fvset{xrightmargin=0pt} - \catcode`\Z=9\relax% - % We suppress the effect of the highlighting macros - \catcode`/=0\relax% - \catcode`?=1\relax% - \catcode`;=2\relax% - \def\HLReverse##1{##1}% - \def\HLMacro##1{##1}% - \def\HLComment##1{##1}% - #1 -\end{minipage}% -\@tempdimb=\textwidth -\advance\@tempdimb -\FV@XRightMargin -\advance\@tempdimb 5mm -\begin{minipage}[c]{\@tempdimb} - \VerbatimInput[gobble=0,commentchar=Z,commandchars=/?;, - numbersep=3pt,frame=single,numbers=left, - xleftmargin=5mm,xrightmargin=0pt]{\jobname.tmp} -\end{minipage}} - -\makeatother - -% Source codes must be indented by 2 spaces -\fvset{gobble=2,frame=single,numbers=left,numbersep=1mm} - -\begin{document} - -\title{The \ArrayJobPackage{} package\\Management of arrays in \AllTeX} -\author{Zhuhan Jiang\\School of Computing and Mathematics\\ - University of Western Sydney\\Sydney\\Australia\\ - {\footnotesize email: zhuhan@scm.uws.edu.au}\\[5mm] - {\footnotesize (Documentation: Denis Girou% - \footnote{All errors and misunderstandings are mine.} - \hspace{1mm}(CNRS/IDRIS -- France) -- - Denis.Girou@idris.fr)}} -\date{Version 1.03\\May 3, 2000\\ - {\small Documentation revised May 31, 2000, edited lightly May 3, 2010 by Michael Sharpe}} - -\maketitle - -\begin{abstract} - This package provides array data structures in \AllTeX, in the meaning of -the classical procedural programming languages like Fortran, Ada or C, and -macros to manipulate them. Arrays can be mono or bi-dimensional. - - This is useful for applications which require high level programming -techniques, like algorithmic graphics programmed in \TeX. This version conflicts with some macros in the {\tt amsmath} package. Version 1.04 resolves those issues. It should be used for all new work. -\end{abstract} - -\tableofcontents - -\section{Introduction} - - One of the big advantages of the \AllTeX{} system over common interactive -software for text processing is that it offer, also, a programming language, -which give, to people who have some knowledge in the algorithmic and -programming fields, an exceptional flexibility and power. - - Nevertheless, \TeX{} is a rather specific programming language, based on -macro expansion, which implements a lot of unusual constructs but lacks some that are very familiar in the classical procedural languages, as -\emph{arrays} to store and retrieve arbitrary pieces of data, stored in a -structured way. The main reason why they were not integrated in \TeX{} was -perhaps that arrays did not seem very useful in a language focussed on text processing (but -\MetaFontPackage{}, for instance, does has them). Nevertheless, one of the few -applications where this is straightforward to use them is to program a mailing -system, where nearly the same information is to be formatted several times, -depending of values which can be simply retrieved from an array of data. This -was the goal of the \FormLettPackage{} package \cite{FORMLETT}, written in -1993-1995 by Zhuhan Jiang for dealing with mass letters, invoices and similar -tasks of some duplicative nature. It implemented a small but powerful set of -macros to manage arrays, which have been extracted to form the present -\ArrayJobPackage{} package. The arrays can be mono or bi-dimensional% -\footnote{You can use more than two dimensions, but not in the meaning of the -classical programming languages (see page \pageref{par:DataHeight})} -and they are dynamically allocated (so we do not have to declare their -dimension statically.)% -\footnote{Stephan von Bechtolsheim \cite[Volume \textsc{III}, paragraph 20.3, -page 136]{SVB93} also demonstrated such macros for array management in the -third volume of his huge book, but it was limited to mono-dimensional -arrays.}. - - Array structures are, at the opposite of text management, often very useful -in graphic programming. This is why the \AlDraTeXPackage{} package from Eitan -Gurari \cite{ALDRATEX} (see also \cite{Gur94}) integrate such functionality -(but which is bundled inside this package and could not be extracted easily -from it), and this is also the case for the \MetaPostPackage{} package -\cite{METAPOST} (but this one do not use \TeX{} as programming language)% -\footnote{Another required feature, used in conjunction with the managements -of arrays, is a generic loop mechanism. \TeX{} offer the \Macro{loop} macro -and \LaTeX{} the \Macro{whiledo} macro of the \IfThenPackage{} package (and -also the internal \Macro{@for}, \Macro{@whilenum}, etc. macros), but a more -high-level structure is to be preferred, as the ones defined too in the -\AlDraTeXPackage{} or \MetaPostPackage{} packages. We will use in our examples -the \MultiDoPackage{} package \cite{MULTIDO}, also written by Timothy van -Zandt, but others are available, like the \RepeatPackage{} package written by -Victor Eijkhout \cite{REPEAT}.}. This fact explain why most of our examples in -this documentation will concern the area of \emph{graphic programming} (here -using the \PSTricksPackage{} package from Timothy van Zandt \cite{PSTRICKS}). - -\section{Command reference} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{newarray}] Define a new array. - - Syntax: !\newarray/Macro?/Variable?ArrayName;;! - - Example: !\newarray\Values! - - \item[\FormatTeXMacro{delarray}] Delete an array. - - Syntax: !\delarray/Macro?/Variable?ArrayName;;! - - Example: !\delarray\Values! - - Remarks: - \begin{enumerate} - \item obviously, elements of a deleted array could not be accessed - later, - \item take care that the elements of a deleted array are not - themselves deleted.\newline - So, \verb+\delarray\Data \newarray\Data \Data(I)+ can produce - strange behavior. Just avoid reusing deleted arrays. - \end{enumerate} - - \item[\FormatTeXMacro{ArrayName}] Store or get the content of the array - element specified by the index/indices. In the last case, the content is - inserted at the current point. - - Syntax: !/Macro?/Variable?ArrayName;;(I)=/Parameter?/Variable?Content;;! or more - generally\newline - \hspace*{1.3cm}!/Macro?/Variable?ArrayName;;(I1,...,In)=/Parameter?/Variable?Content;;! - to store a value - - \hspace{1.3cm}!/Macro?/Variable?ArrayName;;(I)! or more generally - !/Macro?/Variable?ArrayName;;(I1,...,In)! to retrieve a value - - Examples: !\Data(6)={Paul Adams}! - - \hspace{1.75cm}!\Values(19)! - - \item[\FormatTeXMacro{readarray}] Store consecutive values in an array, - starting from the indice one. - - Syntax: !\readarray/Parameter?/Variable?ArrayName;;=/Parameter?/Variable?Content1;&...&/Variable?ContentM;;! - - Example: !\readarray{Actors}{Louise Brooks&Marlene Dietrich&Clark Gable}! - - Remarks: - \begin{enumerate} - \item the values must be separated by the \textbf{\&} character, - \item take care that the trailing spaces are significant, so the - previous definition is different from the following one: - - !\readarray{Actors}{Louise Brooks & Marlene Dietrich & Clark Gable}! - \item you can use \AllTeX{} macros inside the values. - \end{enumerate} -\end{Description} - -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Values - \readarray{/HLReverse?Values;}{A&B&C&D} - \verb+\Values(3)+ = `\Values(3)' - \newarray\Actors - \readarray{/HLReverse?Actors;}{Louise Brooks&Marlene Dietrich&Clark Gable} - Z\par - \verb+\Actors(2)+ = `\Actors(2)' - \readarray{/HLReverse?Actors;}{% - Louise Brooks & Marlene Dietrich & Clark Gable} - Z\par - \verb+\Actors(2)+ = `\Actors(2)' - \Actors(4)={\textit{\underline{Ida Lupino}}} - Z\par - \verb+\Actors(4)+ = `\Actors(4)' -\end{SideBySideExample} - -\vspace{3mm} -\noindent If you really need to trim the unnecessary left and right spaces, you must -apply a special action, like this one: - -\begin{Example} - \def\BS{\texttt{\symbol{`\\}}} - - \newarray\Strings - \readarray{/HLReverse?Strings;}{a& b&c c & d dd ddd } - - \multido{\iString=1+1}{4}{% - \checkStrings(\iString)% - \BS\texttt{Strings(\iString)}=`\cachedata'\qquad} - - \makeatletter - - % /HLComment?A \TrimSpaces macro adapted from Michael J. Downes <epsmjd@ams.org>; - % /HLComment?(posted on c.t.t. June 19, 1998); - % /HLComment?\number`\x reads past one following space (expanding as it goes); - \long\def\TrimSpaces#1{\expandafter\TrimSpaces@i\number`\^^00#1| |} - % /HLComment?Remove the "0" produced by \number`\^^00, and " |" at the end.; - \long\def\TrimSpaces@i 0#1 |{\TrimSpaces@ii\empty#1|} - % /HLComment?" |" was removed by \TrimSpaces@i, now remove a trailing "||" or "| |"; - \long\def\TrimSpaces@ii #1|#2|{#1} - - \makeatother - - \multido{\iString=1+1}{4}{% - \checkStrings(\iString)% - \BS\texttt{Strings(\iString)}=`\TrimSpaces{\cachedata}'\qquad} -\end{Example} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{check}] Get the content of the array element specified - by the indice(s) and store the result in the macro !\cachedata! - - Syntax: !\check/Variable?ArrayName;(I)! or more generally - !\check/Variable?ArrayName;(I1,..,In)! - - Example: !\checkActors(2)! - \item[\FormatTeXMacro{cachedata}] Macro where the content is stored after - a !\check! request. - \item[\FormatTeXMacro{ifemptydata}] True if the last \Macro{check} request - has given an empty result. -\end{Description} - -\newarray\Values -\readarray{Values}{A&B&C&D} - -\newarray\Actors -\newarray\Dates -\newarray\Sexes -\readarray{Actors}{Louise Brooks&% - Marlene Dietrich&% - Clark Gable} -\readarray{Dates}{1906--1985&% - 1902--1992&% - 1901--1960} -\readarray{Sexes}{2&2&1} - -\begin{SideBySideExample}[xrightmargin=6cm] - % /HLComment?Plain TeX usage; - \checkValues(2)% - \verb+\Values(2)+ = `\cachedata' - Z\par - \checkActors(3)% - \verb+\Actors(3)+ = `\cachedata' - Z\par - \checkActors(5)% - \ifemptydata - \verb+\Actors(5)+ not defined. - \fi - Z\par - % /HLComment?LaTeX usage; - \newcommand{\IsEmptyElement}[2]{% - \ifthenelse{\boolean{emptydata}}{#1}{#2}} - \checkActors(3)% - \verb+\Actors(3)+ = \IsEmptyElement{not defined}{`\cachedata'} - Z\par - \checkActors(5)% - \verb+\Actors(5)+ \IsEmptyElement{not defined}{`\cachedata'} -\end{SideBySideExample} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{ifnormalindex}] See below (Default: !\normalindexfalse!). - - \item[\FormatTeXMacro{dataheight}\label{par:DataHeight}] Counter containing - the number of elements in the first dimension, if arrays are bi-dimensional. - - Syntax: !\dataheight=/Variable?Number;! - - Remarks: - \begin{enumerate} - \item arrays are monodimensional when !\dataheight!~$\leq~1$, - \item if !\normalindexfalse! (which is the default value), we have: - $$\hspace{-3cm}\Macro{\Variable{ArrayName}}(I_1,...,I_n) - = \Macro{\Variable{ArrayName}}(I_n + (I_{n-1}-1) * - \Macro{dataheight} + \cdots - + (I_1-1) * \Macro{dataheight}^{n-1})$$ - - and if !\normalindextrue!, we have: - $$\hspace{-3cm}\Macro{\Variable{ArrayName}}(I_1,...,I_n) - = \Macro{\Variable{ArrayName}}(I_1 + (I_2-1) * - \Macro{dataheight} + \cdots - + (I_n-1) * \Macro{dataheight}^{n-1})$$ - \end{enumerate} -\end{Description} - -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Letters - \readarray{/HLReverse?Letters;}{A&B&C&D&E&F&G&H&I&J} - \dataheight=5 - - Z\begin{tabular}{c|c|c|c|c|c|c|c|c|} - Z \multicolumn{1}{c}{} & \multicolumn{1}{c}{1} & \multicolumn{1}{c}{2} & - Z \multicolumn{1}{c}{3} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{5} \\ \cline{2-6} - Z 1 & A & B & C & D & E \\ \cline{2-6} - Z 2 & F & G & H & I & J \\ \cline{2-6} - Z\end{tabular} - Z\\[2mm] - % /HLComment?Default is \normalindexfalse; - \verb+\Letters(1,2)=+`\Letters(1,2)' - Z\par - \verb+\Letters(2,1)=+`\Letters(2,1)' - Z\\[2mm] - Z\begin{tabular}{c|c|c|} - Z \multicolumn{1}{c}{} & \multicolumn{1}{c}{1} & \multicolumn{1}{c}{2} \\ \cline{2-3} - Z 1 & A & F \\ \cline{2-3} - Z 2 & B & G \\ \cline{2-3} - Z 3 & C & H \\ \cline{2-3} - Z 4 & D & I \\ \cline{2-3} - Z 5 & E & J \\ \cline{2-3} - Z\end{tabular} - Z\\[2mm] - \normalindextrue - \verb+\Letters(1,2)=+`\Letters(1,2)' - Z\par - \verb+\Letters(2,1)=+`\Letters(2,1)' -\end{SideBySideExample} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{ifexpandarrayelement}] Boolean macro to allow or not - the element to be evaluated before to be stored in the array (Default: - !\expandarrayelementfalse!). - - Syntax: !\expandarrayelementtrue! or !\expandarrayelementfalse! - - Remark: take care to the possible side effects if you store some macros - as values of some array elements without evaluating them, as they can - change of content later... (see the following examples). -\end{Description} - -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Data - \newcount\CounterP % /HLComment?Plain TeX usage; - \CounterP=3 - \newcounter{CounterL} % /HLComment?LaTeX usage; - \setcounter{CounterL}{3} - \def\Town{Madrid} - \Data(1)={\the\CounterP} - \Data(2)={\the\value{CounterL}} - \Data(3)={\Town} - - \expandarrayelementtrue - \Data(4)={\the\CounterP} - \Data(5)={\the\value{CounterL}} - \Data(6)={\Town} - - \CounterP=5 - \setcounter{CounterL}{5} - \def\Town{Roma} - - \multido{\iData=1+1}{6}{% - \BS\texttt{Data(\iData)}=`\Data(\iData)'\\} -\end{SideBySideExample} - -\vspace{3mm} -\noindent Some other macros exists for mono-dimensional arrays (and only for -them), but have little additional interest: - -\begin{Description}{4cm} - \item[\FormatTeXMacro{array}] Store or get the content of the array element - specified by the index. In the last case, the content is inserted at the - current point.\footnote{The macro name \verb|\array| conflicts with macros in {\tt amsmath}. This is changed in version 1.04.} - - Syntax: !\array/Parameter?/Variable?ArrayName;;(I)=/Parameter?/Variable?Content;;! - to store a value - - \hspace{1.3cm}!\array/Parameter?/Variable?ArrayName;;(I)! to retrieve a value - - Examples: !\array{Actors}(6)={Joan Crawford}! - - \hspace{1.75cm}!\array{Actors}(3)! - - \item[\FormatTeXMacro{clrarray}] Clear the content of the array element specified. - A following inquiry on this element will give an empty content. - - Syntax: !\clrarray/Parameter?/Variable?ArrayName;;(I)! - - Example: !\clrarray{Actors}(2)! - - \item[\FormatTeXMacro{testarray}] Get the content of the array element specified - by the index and store the result in the macro !\temp@macro!% - \footnote{In \LaTeX, this macro should be used inside a package or between - the \verb+\makeatletter+ $\cdots$ \verb+\makeatother+ macro pair.}. - - Syntax: !\testarray/Parameter?/Variable?ArrayName;;(I)! - - Example: !\testarray{Actors}(1)\typeout{Actors(1)=`\temp@macro'}! -\end{Description} - -\section{Examples} - -\UndefineShortVerb{\!} % We will use the ! character in the next examples - - We will first show some basic and easy examples, before looking at more -advanced ones to solve some complex problems, which require more knowledge of -\TeX{} programming techniques. - -\subsection{Basic examples} - - The immediate thing for which we can use arrays is to store and retrieve -information: - -\vspace{2mm} -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Actors - \newarray\Dates - \newarray\Sexes - - \readarray{/HLReverse?Actors;}{Louise Brooks&Marlene Dietrich&Clark Gable} - \readarray{/HLReverse?Dates;}{1906--1985&1902--1992&1901--1960} - \readarray{/HLReverse?Sexes;}{2&2&1} - - \begin{description} - \item[\Actors(1)] : \Dates(1) - \item[\Actors(2)] : \Dates(2) - \item[\Actors(3)] : \Dates(3) - \end{description} -\end{SideBySideExample} - -\vspace{2mm} - But we can also use a general loop macro, as the one provided by the -\MultiDoPackage{} package, for more powerful usage and a management -independent of the number of elements: - -\vspace{2mm} -\begin{SideBySideExample}[xrightmargin=6cm] - \newcommand{\NumberActors}{3} - - \begin{description} - \multido{\iActor=1+1}{\NumberActors}{% - \item[\Actors(\iActor)] : \Dates(\iActor)} - \end{description} -\end{SideBySideExample} - -\vspace{2mm} - This allow various usage in the formatting of texts. A common usage is for a -\emph{mailing} process, when we must compose some similar letters to various -people (as we said previously, this was the reason for which these macros were -developed in the \FormLettPackage{} package). Here, the usage of a programming -language allow a great flexibility, using some conditionals to format the text -differently or even to insert different pieces of text according to the person: - -\newcommand{\NumberActors}{3} - -\begin{CenterExample} - \newcounter{iActor} - - \newcommand{\AccordingSexe}[2]{% - \checkSexes(\the\value{iActor})% - \ifthenelse{\equal{\cachedata}{1}}{#1}{#2}} - - \whiledo{\value{iActor} < \NumberActors}{% - \stepcounter{iActor}% - \fbox{% - \begin{minipage}{0.985\textwidth} - Dear \AccordingSexe{Mr}{Mrs} \Actors(\the\value{iActor}), - - I would like to tell you how I admire the great \AccordingSexe{actor}{actress} - you are, etc. - \end{minipage}}\\[5mm]} -\end{CenterExample} - - Nevertheless, people who know a little \TeX{} as a programming language know -that it behaviour is full of pitfalls... For instance, the following example, -which format a table according to the content of entries stored in external -arrays, can't work: - -\begin{Verbatim} - \begin{tabular}{|l|c|} - \hline - \multicolumn{1}{|c}{\textbf{Actors}} & \multicolumn{1}{|c|}{\textbf{Dates}} \\ \hline - \multido{\iActor=1+1}{\NumberActors}{\Actors(\iActor) & \Dates(\iActor) \\ \hline} - \end{tabular} -\end{Verbatim} - - This is because there is an implicit grouping of each entry in a tabular -environment and that it do not work with the grouping of the \verb+\multido+ -loop. So, this must be program in a different way, storing all the content of -the table before really inserting it: - -\begin{SideBySideExample}[xrightmargin=6cm,baselinestretch=0.9] - \begin{tabular}{|l|c|} - \hline - \multicolumn{1}{|c}{\textbf{Actors}} & - \multicolumn{1}{|c|}{\textbf{Dates}} \\ \hline - \let\ListActors\empty - \begingroup - \let\Actors\relax - \let\Dates\relax - \let\\\relax - \let\hline\relax - \multido{\iActor=1+1}{\NumberActors}{% - \xdef\ListActors{\ListActors - \Actors(\iActor) & \Dates(\iActor) \\ \hline}} - \endgroup - \ListActors - \end{tabular} -\end{SideBySideExample} - -\subsubsection{Plot labels} - - A basic usage in graphic programming is to use arrays to retrieve the labels -to put on a drawing, as here to label the simple plot below. (Note the change from the original documentation. The axis labels used with \verb|\psaxes| must now be numeric, so it is necessary to bypass the automatic axis labeling.) -\ifpstricks % If PSTricks is available -\begin{CenterExample}[baselinestretch=0.9] - \savedata{\Data}[(1,3)(2,1)(3,2)(4,1)(5,1)(6,3),(7,2)(8,1)(9,3)(10,3)(11,1)(12,1)] - - \newcommand{\PlotData}[1]{% - \begin{pspicture}(-0.5,-0.5)(13,4) - \psaxes[labels=none]{->}(13,4) - \dataplot[plotstyle=dots,dotstyle=o,dotsize=0.3]{\Data} - #1\end{pspicture}} - \PlotData{\psaxes[showorigin=false]{->}(13,4)} - - \newarray{\Months} - \readarray{/HLReverse?Months;}{January&February&March&April&May&June&July&August&September&% - October&November&December} - \newarray{\Levels} - \readarray{/HLReverse?Levels;}{Low&Medium&High} - %\renewcommand{\pshlabel}[1]{\tiny\Months(#1)} - \PlotData{\psaxes[labels=y,showorigin=false]{->}(13,4)% - \multido{\i=1+1}{12}{\rput[B](\i,-12pt){\tiny\Months(\i)}}} - - %\renewcommand{\psvlabel}[1]{\small\Levels(#1)} - \PlotData{\multido{\i=1+1}{12}{\rput[B](\i,-12pt){\tiny\Months(\i)}}% - \multido{\i=1+1}{3}{\rput[r](-12pt,\i){\small\Levels(\i)}}} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\subsubsection{Checkboard drawing} - - Of course, a bi-dimensional array directly allow to store the state of a -checkboard of one of the numerous ones existing, like the reversi game that -we will show here (in fact, the only more difficult part to understand in this -example concern the definition of the elementary piece, but as this is not -related at all to the usage of \ArrayJobPackage, this point can be forgotten -by most of the readers). - -\ifpstricks % If PSTricks is available -\begin{SideBySideExample}[xrightmargin=6cm,baselinestretch=0.89] - /HLMacro?\def\Black;{B} - /HLMacro?\def\White;{W} - - /HLMacro?\def\Piece;#1#2{{% - \psset{unit=0.8}% - \pspicture(0,-0.1)(1,0.8) - \pscustom[fillstyle=gradient,gradmidpoint=0,gradangle=90, - gradbegin=#2,gradend=#1]{% - \psbezier(0,0.2)(0.1,-0.2)(0.9,-0.2)(1,0.2) - \psline(1,0.2)(1,0.5) - \psbezier(1,0.5)(0.9,0.9)(0.1,0.9)(0,0.5) - \psline(0,0.5)(0,0.2)} - \psbezier(0,0.5)(0.1,0.1)(0.9,0.1)(1,0.5) - \endpspicture}} - - /HLMacro?\def\PieceBlack;{\Piece{black}{gray}} - /HLMacro?\def\PieceWhite;{\Piece{white}{gray}} - - /HLMacro?\def\CheckboardHook;{} - - \newarray\Checkboard - - /HLMacro?\def\ShowCheckboard;{% - \dataheight=8 - \pspicture(8,8) - \psgrid[subgriddiv=0,gridlabels=0](8,8) - \CheckboardHook - \multido{\iColumn=1+1,\iColumnPos=0+1}{8}{% - \multido{\iRow=1+1,\iRowPos=7+-1}{8}{% - \checkCheckboard(\iRow,\iColumn)% - \ifx\cachedata\Black - \rput(\iColumnPos.5,\iRowPos.5){\PieceBlack} - \else - \ifx\cachedata\White - \rput(\iColumnPos.5,\iRowPos.5){\PieceWhite} - \fi - \fi}} - \endpspicture} - - \readarray{/HLReverse?Checkboard;}{% - W& &B& & & & &B&% - &W&B& & & & &B&% - W&W&B& &W& & &B&% - W&W&B&W&W&W&B&B&% - B& &W&W&W&B&W&B&% - B&B&W&W&W&B&W&B&% - B&B&B&W&W&W&W&B&% - W&B&B&B&B&B&B&B&% - } - - \psset{unit=0.6} - \ShowCheckboard - - \Checkboard(2,1)={B} % /HLComment?Black move; - /HLMacro?\def\CheckboardHook;{% - \psframe[linestyle=none,fillstyle=hlines](0,6)(1,7)} - % /HLComment?White pieces changed by the black move; - \Checkboard(3,1)={B}\Checkboard(4,1)={B} - \Checkboard(2,2)={B}\Checkboard(3,2)={B} - \vspace{1cm} - \ShowCheckboard -\end{SideBySideExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - - Note also that, if \TeX{} is obviously not well suited to implement a -program to \emph{really} play at a game like reversi or chess, nevertheless -it can be used to solve internally some non trivial algorithmic problems, -where the usage of arrays help a lot. For such example (on the coloration of -the Truchet's tiling), see \cite{EG98}. - -\subsection{Advanced examples} - - This section will show slightly more difficult to really complex examples, -and is mainly for \emph{advanced users} or for people who want to be able to -program complex tasks themselves. - -\subsubsection{Example with recursion usage} - -\begin{CenterExample} - \makeatletter - - % /HLComment?The recursion macro used (from David Carlisle); - /HLMacro?\def\Recursion;#1{% - #1\relax - \expandafter\@firstoftwo - \else - \expandafter\@secondoftwo - \fi} - - \newcount\IndexRecursion - \IndexRecursion=\z@ - - /HLMacro?\def\PiFrac;#1{{% - \Recursion - {\ifnum#1>\@ne\relax} - {\@tempcnta=#1 - \advance\@tempcnta\m@ne - \advance\IndexRecursion\@ne - \PiValues(\IndexRecursion) - +\frac{\strut\displaystyle 1}{\strut\displaystyle\PiFrac{\@tempcnta}}} - {\advance\IndexRecursion\@ne - \PiValues(\IndexRecursion)}}} - - \makeatother - - \newarray\PiValues - \readarray{/HLReverse?PiValues;}{3&7&15&1&292&1&1&1&2&1&3&1&14} - - \(\pi\approx\PiFrac{/HLReverse?4;}\approx\PiFrac{/HLReverse?13;}\) - - \textbf{\(\pi\) as a continued fraction} -\end{CenterExample} - -\subsubsection{Structured dynamic diagrams on a grid} - - A very common case is when we must use some strutured data which are to be -drawn on a kind of abstract grid. - -\ifpstricks % If PSTricks is available - To draw a diagram like this one (such example illustrate the exchanges of -data between processors when using applications on multiprocessors computers -in parallel programming): - -\vspace{2mm} -\begin{SideBySideExample}[xrightmargin=5.8cm] - \psset{linestyle=none,fillstyle=solid,subgriddiv=0,gridlabels=0} - \begin{pspicture}(-1,0)(4,4) - % /HLComment?Line 0; - \psframe[fillcolor=Khaki](0,3.1)(1,3.9) - \psframe[fillcolor=LemonChiffon](1,3.1)(4,3.9) - \rput(0,3.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,3.5){P0} - \rput(0.5,3.5){A0} - % /HLComment?Line 1; - \psframe[fillcolor=Khaki](0,2.1)(2,2.9) - \psframe[fillcolor=LemonChiffon](2,2.1)(4,2.9) - \rput(0,2.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,2.5){P1} - \rput(0.5,2.5){A0}\rput(1.5,2.5){A1} - % /HLComment?Line 2; - \psframe[fillcolor=Khaki](0,1.1)(3,1.9) - \psframe[fillcolor=LemonChiffon](3,1.1)(4,1.9) - \rput(0,1.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,1.5){P2} - \rput(0.5,1.5){A0}\rput(1.5,1.5){A1}\rput(2.5,1.5){A2} - % /HLComment?Line 3; - \psframe[fillcolor=Khaki](0,0.1)(4,0.9) - \rput(0,0.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,0.5){P3} - \rput(0.5,0.5){A0}\rput(1.5,0.5){A1} - \rput(2.5,0.5){A2}\rput(3.5,0.5){A3} - \end{pspicture} -\end{SideBySideExample} - -\vspace{2mm} -\noindent is easy but rather painful, as we must manage a lot of coordinates. -Nevertheless, even if we introduce a little more abstraction level using some -minor programming with a loop structure: -\vspace{2mm} - - -\begin{SideBySideExample}[xrightmargin=5.8cm] - \psset{linestyle=none,fillstyle=solid,subgriddiv=0,gridlabels=0} - \begin{pspicture}(-1,0)(4,4) - \multido{\iLoop=1+1,\iRow=0+1,\iRowPos=3+-1}{4}{% - \psframe[fillcolor=Khaki](0,\iRowPos.1)(\iLoop,\iRowPos.9) - \psframe[fillcolor=LemonChiffon] - (\iLoop,\iRowPos.1)(4,\iRowPos.9) - \rput(0,\iRowPos.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,\iRowPos.5){P\iRow} - \multido{\iColumn=0+1,\iLabel=1+1}{\iLoop}{% - \rput(\iColumn.5,\iRowPos.5){A\iColumn}}} - \end{pspicture} -\end{SideBySideExample} - -\vspace{2mm} -\noindent we succeed to heavily reduce the number of lines of the code in this -specific case, but we gain nothing in genericity. If we have several such -diagrams to draw, with each that must be done differently according to the -empty and full cells of the array, we must proceed in a completely different -way, defining a \emph{generic object} which can obtain the different values of -a data structure previously filled. For such tasks, the \ArrayJobPackage{} -package allow to build very efficient and powerful tools. - -\begin{Verbatim}[commandchars=/?;] - % /HLComment?The grid; - /HLMacro?\def\ArrayGrid;#1#2#3{{% - % /HLComment?#1=array of data, #2=number of rows, #3=number of columns; - \psset{dimen=middle,xunit=0.8} - \dataheight=#3 - \pspicture(-1,-#2)(#3,0) - \multido{\iRow=1+1,\iRowMinusOne=0+1}{#2}{% - \rput(-1,-\iRow){\LineGrid{#1}{\iRow}{\iRowMinusOne}{#3}}} - \endpspicture}} - - % /HLComment?One line of the grid; - /HLMacro?\def\LineGrid;#1#2#3#4{% - \rput(0.5,0.4){\AttributeLabel{P#3}} - \multido{\iColumn=1+1}{#4}{% - \expandafter\csname check#1\endcsname(#2,\iColumn)% - \rput(\iColumn,0){% - \ifemptydata - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \ifx\cachedata\space - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \def\ColorBackground{\ColorBackgroundFull}% - \fi - \fi - \psframe[fillstyle=solid,fillcolor=\ColorBackground](1,0.8) - \rput(0.5,0.4){\AttributeElement{\cachedata}}}}} -\end{Verbatim} - -% The grid -\def\ArrayGrid#1#2#3{{% -% #1=array of data, #2=number of rows, #3=number of columns -\psset{dimen=middle,xunit=0.8} -\dataheight=#3 -\pspicture(-1,-#2)(#3,0) -\multido{\iRow=1+1,\iRowMinusOne=0+1}{#2}{% - \rput(-1,-\iRow){\LineGrid{#1}{\iRow}{\iRowMinusOne}{#3}}} -\endpspicture}} - -% One line of the grid -\def\LineGrid#1#2#3#4{% -\rput(0.3,0.4){\AttributeLabel{P#3}} -\multido{\iColumn=1+1}{#4}{% - \expandafter\csname check#1\endcsname(#2,\iColumn)% - \rput(\iColumn,0){% - \ifemptydata - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \ifx\cachedata\space - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \def\ColorBackground{\ColorBackgroundFull}% - \fi - \fi - \psframe[fillstyle=solid,fillcolor=\ColorBackground](1,0.8) - \rput(0.5,0.4){\AttributeElement{\cachedata}}}}} - -\begin{SideBySideExample}[xrightmargin=6cm] - % /HLComment?Default attributes; - \def\ColorBackgroundEmpty{LemonChiffon} - \def\ColorBackgroundFull{Khaki} - \def\AttributeElement#1{\textcolor{red}{#1}} - \def\AttributeLabel#1{\bf #1} - - % /HLComment?Example 1; - \newarray\ArrayA - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A0& & & &% - A0&A1& & &% - A0&A1&A2& &% - A0&A1&A2&A3} - - \ArrayGrid{ArrayA}{4}{4} -\end{SideBySideExample} - -\newarray\ArrayA - -% Default attributes -\def\ColorBackgroundEmpty{LemonChiffon} -\def\ColorBackgroundFull{Khaki} -\def\AttributeElement#1{\textcolor{red}{#1}} -\def\AttributeLabel#1{\bf #1} - -\begin{CenterExample}[baselinestretch=0.9] - % /HLComment?Example 2; - \newarray\ArrayB - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A& & & &% - & & & &% - & & & &% - & & & } - \readarray{/HLReverse?ArrayB;}{% - A& & & &% - A& & & &% - A& & & &% - A& & & } - - \ArrayGrid{ArrayA}{4}{4}\hfill\ArrayGrid{ArrayB}{4}{4} -\end{CenterExample} - -\newarray\ArrayB - -\begin{CenterExample}[baselinestretch=0.9] - % /HLComment?Example 3; - \newarray\ArrayC - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A0& & &% - A1& & &% - A2& & } - \readarray{/HLReverse?ArrayB;}{% - A0&A1&A2&% - A0&A1&A2&% - A0&A1&A2} - \readarray{/HLReverse?ArrayC;}{% - A0& & &% - &A1& &% - & &A2} - - % /HLComment?Attributes; - \def\ColorBackgroundEmpty{green} - \def\ColorBackgroundFull{red} - \def\AttributeElement#1{\footnotesize\textcolor{white}{#1}} - \def\AttributeLabel#1{\small\bf #1} - - \psset{unit=0.7} - \ArrayGrid{ArrayA}{3}{3}\hfill\ArrayGrid{ArrayB}{3}{3}\hfill\ArrayGrid{ArrayC}{3}{3} -\end{CenterExample} - -\begin{CenterExample}[baselinestretch=0.9] - % /HLComment?Example 4; - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A0&A1&A2&A3&% - B0&B1&B2&B3&% - C0&C1&C2&C3&% - D0&D1&D2&D3} - \readarray{/HLReverse?ArrayB;}{% - A0&B0&C0&D0&% - A1&B1&C1&D1&% - A2&B2&C2&D2&% - A3&B3&C3&D3} - - % /HLComment?Attributes; - \def\AttributeElement#1{\textcolor{red}{#1}} - \def\AttributeLabel#1{\Large\it #1} - - \ArrayGrid{ArrayA}{4}{4}\hfill\ArrayGrid{ArrayB}{4}{4} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\vspace{5mm} -\subsubsection{Another example of a structured dynamic diagram on a grid} - - The preceding technique is in fact relevant for a lot of problems. Here we -give another example about the drawing of linked lists (but do not fail to -note that these ones have here no internal existence). - -\ifpstricks % If PSTricks is available -\begin{CenterExample} - \makeatletter - - \newpsstyle{LinkedListsArrowStyle}{linecolor=red,arrowscale=2} % /HLComment?Default arrow style; - - /HLMacro?\def\LinkedListsDraw;{\@ifnextchar[\LinkedListsDraw@i{\LinkedListsDraw@i[]}} - - /HLMacro?\def\LinkedListsDraw@i;[#1]#2#3{{% - \setkeys{psset}{#1} - \dataheight=#3 - % - \pst@cnta=#3 - \multiply\pst@cnta\tw@ - \advance\pst@cnta\tw@ - \pspicture(0,-#2)(\pst@cnta,0) - \multido{\iRow=1+1}{#2}{% - \rput(0,-\iRow){% - \psframe(1,1) - \psline[dimen=middle,style=LinkedListsArrowStyle]{->}(0.5,0.5)(2,0.5)} - \multido{\iColumn=1+1}{#3}{% - \checkLinkedListsTable(\iRow,\iColumn)% - \ifemptydata - \else - \pst@cnta=\iColumn - \advance\pst@cnta\@ne - \pst@cntb=\@ne - \checkLinkedListsTable(\iRow,\pst@cnta)% - \ifemptydata % /HLComment?We test if it is empty; - \else - \ifnum\multidocount=#3 % /HLComment?We test if it is the last one; - \else - \pst@cntb=\z@ - \fi - \fi - % - \pst@cnta=\iColumn - \multiply\pst@cnta\tw@ - \rput(\the\pst@cnta,-\iRow){% - \LinkedListsDraw@ii{\LinkedListsTable(\iRow,\iColumn)}{\the\pst@cntb}} - \fi}} - \endpspicture}}%} - - /HLMacro?\def\LinkedListsDraw@ii;#1#2{{% - \rput(0,0.1){% - \psset{unit=0.8} - \psgrid[subgriddiv=0,gridlabels=0](2,1) % /HLComment?Element; - \rput(0.5,0.5){#1} % /HLComment?Label for this element; - \ifnum#2=\@ne - \psline(1,0)(2,1) % /HLComment?Mark of the end of the list; - \else - \psline[style=LinkedListsArrowStyle]{->}(1.5,0.5)(2.5,0.5) % /HLComment?Link to the next element; - \fi}}} - - \makeatother - - \newarray\LinkedListsTable - \readarray{/HLReverse?LinkedListsTable;}{% - 11&12&13&14&% - 21&&&&% - 31&32&33&&} - - \LinkedListsDraw{3}{4} - - \vspace{1cm} - \newpsstyle{LinkedListsArrowStyle}{linecolor=green,doubleline=true} - - \readarray{/HLReverse?LinkedListsTable;}{% - a&&&&&% - A&B&C&D&E&% - 0&1&2&3&4&% - +&$\times$&&&&} - - \LinkedListsDraw{4}{5} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\subsubsection{Management of heaps and linked lists} - - Here we will demonstrate a really more complex usage, but very useful. -In fact, if the \ArrayJobPackage{} package primarily allow to manage only -arrays, it allow a lot more with some efforts. Above it, we can implement the -common internal data structures frequently used in programming, like heaps, -simple or double linked lists, trees, associative arrays, etc. Here we will -show how to define macros to build and manage heaps and simple linked lists. - -\ifpstricks % If PSTricks is available -\vspace{1cm} % Poor hack to force a page break... -\begin{CenterExample}[baselinestretch=0.98] - \makeatletter - - /HLMacro?\def\PstDebug;{\z@} % /HLComment?For debugging, set \def\PstDebug{1}; - - % /HLComment?Code for heaps management; - % /HLComment?-------------------------; - - /HLMacro?\def\HeapMaxDepth;{100} % /HLComment?No more than 100 elements in the heap; - - \newarray\Heap - - % /HLComment?Add an element at top of the heap; - /HLMacro?\def\HeapPush;#1{% - \multido{\iElem=1+1}{\HeapMaxDepth}{% - \checkHeap(\iElem)% - \ifemptydata - \ifnum\PstDebug=\@ne\typeout{Push Heap(\iElem)=#1}\fi% /HLComment?Debug; - \Heap(\iElem)={#1}% - \multidostop - \fi}} - - % /HLComment?Get (in the \cachedata macro) and delete the element at top of the heap; - /HLMacro?\def\HeapPop;{% - \Multido{\iElem=\HeapMaxDepth+-1}{\HeapMaxDepth}{% - \checkHeap(\iElem)% - \ifemptydata - \else - \ifnum\PstDebug=\@ne\typeout{Delete Heap(\iElem)=\cachedata}\fi% /HLComment?Debug; - \Heap(\iElem)={}% - \multidostop - \fi}} - - % /HLComment?Print the current state of the heap; - /HLMacro?\def\HeapPrint;{% - \checkHeap(\@ne)% - \ifemptydata - \typeout{The heap is empty!}% /HLComment?Empty heap; - \else - \multido{\iElem=\HeapMaxDepth+-1}{\HeapMaxDepth}{% - \checkHeap(\iElem)% - \ifemptydata - \else - \typeout{Heap(\iElem)=\cachedata}% - \fi} - \fi - \typeout{}} - - % /HLComment?Draw the current state of the heap; - /HLMacro?\def\HeapDraw;{% - % /HLComment?To compute the size of the picture; - \Multido{\iSize=0+1}{\HeapMaxDepth}{% - \checkHeap(\the\multidocount)% - \ifemptydata - \multidostop - \fi} - % - \ifnum\iSize=\z@ - % /HLComment?Empty heap; - \typeout{The heap is empty!^^J}% - \else - \pspicture(1,\iSize) - \psgrid[subgriddiv=0,gridlabels=0](1,\iSize) - \multido{\iPos=0+1}{\HeapMaxDepth}{% - \checkHeap(\the\multidocount)% - \ifemptydata - \multidostop - \else - \rput(0.5,\iPos.5){\cachedata} - \fi} - \endpspicture% - \fi} - - \makeatother - - \psset{unit=1.5}\footnotesize - - \HeapPush{Germany}\HeapPrint\HeapDraw - \hfill - \HeapPush{France}\HeapPrint\HeapDraw - \hfill - \HeapPush{Italy}\HeapPrint\HeapDraw - \hfill - \HeapPush{Spain}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw -\end{CenterExample} - -\begin{Example}[baselinestretch=0.95] - \makeatletter - - /HLMacro?\def\PstDebug;{\z@}% /HLComment?For debugging, set \def\PstDebug{1}; - - % /HLComment?Code for linked lists management; - % /HLComment?--------------------------------; - - /HLMacro?\def\LinkedListMaxDepth;{100}% /HLComment?No more than 100 elements in the list; - - \newarray\LinkedList - - \dataheight=2% /HLComment?Two cells by element: the content and the pointer; - - % /HLComment?Add an element at the end of the list; - % /HLComment?In fact, we define it here as a simple heap, but the difference is that; - % /HLComment?we will be able to get and to delete any element in it; - /HLMacro?\def\LinkedListAdd;#1{% - \edef\@tempa{\@ne}% /HLComment?Pointer initialization; - \multido{\iElem=2+1}{\LinkedListMaxDepth}{% - \checkLinkedList(\@tempa,2)% /HLComment?We got the content of this element; - \ifemptydata - % /HLComment?No pointed element, so we will insert the new one here; - \LinkedList(\iElem,1)={#1}% - % /HLComment?We update the pointer for the last preceding element; - \expandarrayelementtrue% /HLComment?We must evaluate the content of the counter; - \LinkedList(\@tempa,2)={\iElem}% - \expandarrayelementfalse - \ifnum\PstDebug=\@ne - \typeout{Add LinkedList(\@tempa)->\iElem}% /HLComment?Debug; - \typeout{\space\space\space\space LinkedList(\iElem)=#1}% /HLComment?Debug; - \fi - \multidostop - \else - \edef\@tempa{\cachedata}% - \fi}} - - % /HLComment?Get (in the \cachedata macro) the next element in the list; - /HLMacro?\def\LinkedListGetNext;#1{% - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \edef\@tempa{\@ne}% - \ifx\cachedata\empty - \else - \edef\@tempc{#1}% - \Multido{}{\LinkedListMaxDepth}{% - \edef\@tempb{\@tempa}% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \ifx\cachedata\@tempc - % /HLComment?This is the element for which we want the next one: we got it pointer; - % /HLComment?to the next element in the list, then the content of it; - \checkLinkedList(\@tempa,2)% - \ifemptydata - \typeout{Element `#1' has no successor!^^J}% - \else - \checkLinkedList(\cachedata,1)% - \fi - \multidostop - \else - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - % /HLComment?We have reach the end of the list without finding the element; - \typeout{Element `#1' not found!^^J}% - \multidostop% /HLComment?No pointed element: end of the list; - \fi - \fi} - \fi} - - % /HLComment?Delete an element in the list (the code is very close to \LinkedListGetNext); - /HLMacro?\def\LinkedListDelete;#1{% - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \edef\@tempa{\@ne}% - \ifx\cachedata\empty - \else - \edef\@tempc{#1}% - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempb{\@tempa}% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \ifx\cachedata\@tempc - % /HLComment?This is the element to delete: we will update the pointer of; - % /HLComment?the preceding element to the value of the pointer of the deleted one; - \checkLinkedList(\@tempa,2)% - \expandarrayelementtrue - \LinkedList(\@tempb,2)={\cachedata}% - \expandarrayelementfalse - \ifnum\PstDebug=\@ne - \typeout{Delete LinkedList(\@tempa)=#1}% /HLComment?Debug; - \typeout{\space\space\space\space\space\space\space % - LinkedList(\@tempb)->\cachedata}% /HLComment?Debug; - \fi - \multidostop - \else - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - % /HLComment?We have reach the end of the list without finding the element; - \typeout{Element `#1' not found and so not deleted!^^J}% - \multidostop% /HLComment?No pointed element: end of the list; - \fi - \fi} - \fi} - - % /HLComment?Print the current state of the list; - /HLMacro?\def\LinkedListPrint;{% - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \ifx\cachedata\empty - % /HLComment?Empty list; - \typeout{The list is empty!}% - \else - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \typeout{LinkedList=\cachedata}% - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - \multidostop% /HLComment?No pointed element: end of the list; - \fi} - \fi - \typeout{}} - - % /HLComment?Draw the current state of the list; - /HLMacro?\def\LinkedListDraw;{{% - \psset{subgriddiv=0,gridlabels=0} - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \ifx\cachedata\empty - % /HLComment?Empty list; - \typeout{The list is empty!^^J}% - \else - % /HLComment?To compute the size of the picture; - \Multido{\iSize=3+3}{\LinkedListMaxDepth}{% - \checkLinkedList(\cachedata,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - \multidostop - \fi} - % - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \pspicture(\iSize,1.5) - \multido{\iPos=0+3}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \rput(\iPos,0){% - \psgrid(2,1) - \rput(0.5,0.5){\cachedata} - \ifnum\iPos=\z@ - \else - \rput(-1.5,0.5){\psline[linecolor=red,arrowscale=2]{->}(1.5,0)} - \fi} - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - \rput(\iPos,0){\psline[linecolor=red](1,0)(2,1)} % /HLComment?End of the list; - \multidostop% /HLComment?No pointed element: end of the list; - \fi} - \endpspicture% - \fi}} - - \makeatother - - \psset{unit=1.5} - - \LinkedListPrint\LinkedListDraw - - \LinkedListAdd{Germany}\LinkedListPrint\LinkedListDraw - - \LinkedListAdd{France}\LinkedListPrint\LinkedListDraw - - \LinkedListAdd{Italy}\LinkedListPrint\LinkedListDraw - - \LinkedListAdd{Spain}\LinkedListPrint\LinkedListDraw - - \LinkedListGetNext{France}\typeout{Next element after `France' is: `\cachedata'}% - \LinkedListGetNext{Germany}\typeout{Next element after `Germany is: `\cachedata'}% - \LinkedListGetNext{Spain} - \LinkedListGetNext{Unknown} - - \LinkedListDelete{Unknown} - - \LinkedListDelete{France}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{Germany}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{Spain}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{Italy}\LinkedListPrint\LinkedListDraw -\end{Example} - -\makeatletter - -\def\PstDebug{\z@}% For debugging, set \def\PstDebug{1} - -\def\LinkedListMaxDepth{100}% No more than 100 elements in the heap - -\newarray\LinkedList - -\dataheight=2% Two cells by element: the content and the pointer - -% Delete an element in the list -\def\LinkedListDelete#1{% -\checkLinkedList(1,2)% We got the pointer for the first element -\edef\@tempa{\@ne}% -\ifx\cachedata\empty -\else - \edef\@tempc{#1}% - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempb{\@tempa}% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% We got the pointed element - \ifx\cachedata\@tempc - % This is the element to delete: we will update the pointer of - % the preceding element to the value of the pointer of the deleted one - \checkLinkedList(\@tempa,2)% - \expandarrayelementtrue - \LinkedList(\@tempb,2)={\cachedata}% - \expandarrayelementfalse - \ifnum\PstDebug=\@ne - \typeout{Delete LinkedList(\@tempa)=#1}%Debug - \typeout{\space\space\space\space\space\space\space % - LinkedList(\@tempb)->\cachedata}%Debug - \fi - \multidostop - \else - \checkLinkedList(\@tempa,2)% We got the pointer to the next element - \ifemptydata - % We have reach the end of the list without finding the element - \typeout{Element `#1' not found and so not deleted!^^J}% - \multidostop% No pointed element: end of the list - \fi - \fi} -\fi} - -% Print the current state of the list -\def\LinkedListPrint{% -\checkLinkedList(1,2)% We got the pointer for the first element -\ifx\cachedata\empty - % Empty list - \typeout{The list is empty!}% -\else - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% We got the pointed element - \typeout{LinkedList=\cachedata}% - \checkLinkedList(\@tempa,2)% We got the pointer to the next element - \ifemptydata - \multidostop% No pointed element: end of the list - \fi} -\fi -\typeout{}} - -% Draw the current state of the list -\def\LinkedListDraw{{% -\psset{subgriddiv=0,gridlabels=0} -\checkLinkedList(1,2)% We got the pointer for the first element -\ifx\cachedata\empty - % Empty list - \typeout{The list is empty!^^J}% -\else - % To compute the size of the picture - \Multido{\iSize=3+3}{\LinkedListMaxDepth}{% - \checkLinkedList(\cachedata,2)% We got the pointer to the next element - \ifemptydata - \multidostop - \fi} - % - \checkLinkedList(1,2)% We got the pointer for the first element - \pspicture(\iSize,1.5) - \multido{\iPos=0+3}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% We got the pointed element - \rput(\iPos,0){% - \psgrid(2,1) - \rput(0.5,0.5){\cachedata} - \ifnum\iPos=\z@ - \else - \rput(-1.5,0.5){\psline[linecolor=red,arrowscale=2]{->}(1.5,0)} - \fi} - \checkLinkedList(\@tempa,2)% We got the pointer to the next element - \ifemptydata - \rput(\iPos,0){\psline[linecolor=red](1,0)(2,1)} % End of the list - \multidostop% No pointed element: end of the list - \fi} - \endpspicture% -\fi}} - -\makeatother - -% We clear the linked list -\multido{\iElem=1+1}{\LinkedListMaxDepth}{% - \checkLinkedList(\iElem,1)% - \ifemptydata - \else - \LinkedList(\iElem,1)={}% - \LinkedList(\iElem,2)={}% - \fi} - -\vspace{2mm} - We can write an extended version of the inclusion of an element, where we do -not still store each element at the end of the list, but insert it at a -special position. For instance, we can decide to use the list to sort the -elements, inserting a new one at it sorted position. In the next example, we -will manage integer numbers in this way (of course, we can do the same thing -with arbitrary strings, but it would be more difficult to program in \TeX{}, -mainly if we want to be able to use accentuated letters). - -\vspace{2mm} -\begin{Example} - \makeatletter - - % /HLComment?Add an element at the end of the list, linked in it ordered place; - % /HLComment?(this version work only with contents as numbers); - /HLMacro?\def\LinkedListSortedAdd;#1{% - % /HLComment?Initializations; - \edef\@tempa{\@ne}% - \edef\@tempb{\@ne}% - \edef\@tempc{\z@}% - % - \multido{\iElem=2+1}{\LinkedListMaxDepth}{% - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer of this element; - \ifemptydata - % /HLComment?No pointed element, so we will insert the new one here; - \LinkedList(\iElem,1)={#1}% - % /HLComment?We update the pointer for the last element; - \expandarrayelementtrue - \LinkedList(\@tempb,2)={\iElem}% - \ifnum\PstDebug=\@ne - \typeout{Add LinkedList(\@tempb)->\iElem}% /HLComment?Debug; - \typeout{\space\space\space\space LinkedList(\iElem)=#1}% /HLComment?Debug; - \fi - % /HLComment?We update the pointer of the new element to the position; - % /HLComment?of the next greater one, if it exist; - \ifnum\@tempc=\z@ - \else - \LinkedList(\iElem,2)={\@tempc}% - \ifnum\PstDebug=\@ne - \typeout{Update LinkedList(\iElem)->\@tempc}% /HLComment?Debug; - \fi - \fi - \expandarrayelementfalse - \multidostop - \else - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% - \ifnum#1<\cachedata - \edef\@tempc{\@tempa}% /HLComment?New element less than this one; - \else - \edef\@tempb{\@tempa}% /HLComment?New element greater or equal than this one; - \fi - \fi}} - - \makeatother - - \LinkedListPrint - - \LinkedListSortedAdd{732}\LinkedListPrint\LinkedListDraw - - \LinkedListSortedAdd{487}\LinkedListPrint\LinkedListDraw - - \LinkedListSortedAdd{718}\LinkedListPrint\LinkedListDraw - - \LinkedListSortedAdd{962}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{487}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{732}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{500} - - \LinkedListDelete{962}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{718}\LinkedListPrint\LinkedListDraw -\end{Example} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\subsubsection{Associative arrays} - - To finish, we will give a complete solution to a classical problem: to count -the number of occurrences of the various letters in a sentence. For this, we -will first build some macros to deal with \emph{associative} arrays, as they -have been popularized by scripting languages like \texttt{AWK} and -\texttt{Perl}. - -\begin{Example} - \makeatletter - - % /HLComment?Internally, we use two "standard" arrays to define one associative array; - \newarray\AssociativeArray@Names - \newarray\AssociativeArray@Values - - \newcount\AssociativeArrayNbValues - \AssociativeArrayNbValues=\z@ - - \newif\ifAssociativeArray@ElementFound - - % /HLComment?To store one element; - /HLMacro?\def\AssociativeArray;(#1)=#2{% - \expandarrayelementtrue - \AssociativeArray@ElementFoundfalse - \edef\@tempa{#1}% - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % /HLComment?This element already exist: we replace it current value; - % /HLComment?\checkAssociativeArray@Values(\iValue)% Debug; - % /HLComment?\typeout{In #1, replace `\cachedata'\space by `#2'}% Debug; - \AssociativeArray@Values(\iValue)={#2}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} - \ifAssociativeArray@ElementFound - \else - % /HLComment?New element; - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={#1}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={#2}% - \fi} - - % /HLComment?To get one element; - /HLMacro?\def\checkAssociativeArray;(#1){% - \edef\@tempa{#1}% - \edef\@tempb{999999}% - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % /HLComment?We have found it by name; - \edef\@tempb{\iValue}% - \multidostop - \fi} - % /HLComment?We have now to get it value; - \checkAssociativeArray@Values(\@tempb)} - - % /HLComment?Simple macro to print all the associative array; - /HLMacro?\def\printAssociativeArray;{% - \multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \iValue: \BS\texttt{FirstNames(\cachedata)}=`\AssociativeArray@Values(\iValue)'\space}} - - \makeatother - - \let\FirstNames\AssociativeArray - \let\checkFirstNames\checkAssociativeArray - \let\printFirstNames\printAssociativeArray - - \FirstNames(Crawford)={Joan} - \FirstNames(Tierney)={Gene} - \FirstNames(Lake)={Veronika} - - \printFirstNames - - \checkFirstNames(Lake) - \verb+\FirstNames(Lake)+=`\cachedata' - - \checkFirstNames(Monroe) - \ifemptydata - \verb+\FirstNames(Monroe) undefined!+ - \else - \verb+\FirstNames(Monroe)+=`\cachedata' - \fi -\end{Example} - -\makeatletter - -% Internally, we use two "standard" arrays to define one associative array -\newarray\AssociativeArray@Names -\newarray\AssociativeArray@Values - -\newcount\AssociativeArrayNbValues -\AssociativeArrayNbValues=\z@ - -\newif\ifAssociativeArray@ElementFound - -% To store one element -\def\AssociativeArray(#1)=#2{% -\expandarrayelementtrue -\AssociativeArray@ElementFoundfalse -\edef\@tempa{#1}% -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % This element already exist: we replace it current value - % \checkAssociativeArray@Values(\iValue)% debug - % \typeout{In #1, replace `\cachedata'\space by `#2'}% Debug - \AssociativeArray@Values(\iValue)={#2}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} -\ifAssociativeArray@ElementFound -\else - % New element - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={#1}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={#2}% -\fi} - -% To get one element -\def\checkAssociativeArray(#1){% -\edef\@tempa{#1}% -\edef\@tempb{999999}% -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % We have found it by name - \edef\@tempb{\iValue}% - \multidostop - \fi} -% We have now to get it value -\checkAssociativeArray@Values(\@tempb)} - -% Simple macro to print all the associative array -\def\printAssociativeArray{% -\multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \iValue: \BS\texttt{FirstNames(\cachedata)}=`\AssociativeArray@Values(\iValue)'}} - -\makeatother - -\vspace{2mm} - Now, we can define the macros to read a sentence, to cut it letter by letter, -to count the occurrences of each of them, and finally to draw a summary plot of -the results. - -\makeatletter % Problem with the \ifpstricks conditional if not set... - -\ifpstricks % If PSTricks is available -\begin{CenterExample} - \makeatletter - - % /HLComment?A \PerChar style macro adapted from Juergen Schlegelmilch; - % /HLComment?(<schlegel@Informatik.Uni-Rostock.de> - posted on c.t.t. January 27, 1998); - /HLMacro?\def\PerChar;#1#2{\DoPerChar#1#2\@nil} - - /HLMacro?\def\DoPerChar;#1#2#3\@nil{% - #1#2% - \edef\@tempa{#3}% - \ifx\@tempa\empty - \else - \DoPerChar#1#3\@nil - \fi} - - % /HLComment?The action to do for each character: we increase the counter; - % /HLComment?for this character by one; - /HLMacro?\def\ActionPerChar;#1{% /HLComment?#1=character; - \checkAssociativeArray(#1)% - \ifemptydata - \@tempcnta=\@ne - \else - \@tempcnta=\cachedata - \advance\@tempcnta\@ne - \fi - \AssociativeArray(#1)={\the\@tempcnta}} - - % /HLComment?To store in an associative array the number of occurrences by characters; - % /HLComment?(spaces are not counted); - /HLMacro?\def\StatSentence;#1{% /HLComment?#1=sentence; - \AssociativeArrayNbValues=\z@ - \PerChar{\ActionPerChar}{#1}} - - % /HLComment?To draw a plot of the number of occurrences of the characters of a sentence; - /HLMacro?\def\DrawOccurrences;#1{% /HLComment?#1=sentence; - \StatSentence{#1} - % - \pst@cnta=\AssociativeArrayNbValues - \advance\pst@cnta\@ne - % - % /HLComment?To know the maximum of the numbers; - \pst@cntb=\z@ - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Values(\iValue)% - \ifnum\cachedata>\pst@cntb - \pst@cntb=\cachedata - \fi} - \advance\pst@cntb\@ne - % - % /HLComment?The drawing itself; - \pspicture(-0.5,-0.5)(\pst@cnta,\pst@cntb) - \psaxes[axesstyle=frame,labels=y](\pst@cnta,\pst@cntb) - \multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \Draw@OneOccurrence{\iValue}} - \endpspicture} - - % /HLComment?To draw the value for one occurrence; - /HLMacro?\def\Draw@OneOccurrence;#1{% /HLComment?#1=Letter; - \checkAssociativeArray@Values(#1)% - \psdot(#1,\cachedata) - \rput[B](\iValue,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \let\Names\AssociativeArray - \let\checkNames\checkAssociativeArray - - \psset{dotstyle=o,dotsize=0.4} - - \DrawOccurrences{We are Wednesday} -\end{CenterExample} - -\makeatletter - -%% A \PerChar style macro adapted from Juergen Schlegelmilch -%% (<schlegel@Informatik.Uni-Rostock.de> - posted on c.t.t. Jan. 27, 1998) -\def\PerChar#1#2{\DoPerChar#1#2\@nil} - -\def\DoPerChar#1#2#3\@nil{% -#1#2% -\edef\@tempa{#3}% -\ifx\@tempa\empty -\else - \DoPerChar#1#3\@nil -\fi} - -% The action to do for each character: we increase the counter -% for this character by one -\def\ActionPerChar#1{% #1=character -\checkAssociativeArray(#1)% -\ifemptydata - \@tempcnta=\@ne -\else - \@tempcnta=\cachedata - \advance\@tempcnta\@ne -\fi -\AssociativeArray(#1)={\the\@tempcnta}} - -% To store in an associative array the number of occurrences by characters -% (spaces are not counted) -\def\StatSentence#1{% #1=sentence -\AssociativeArrayNbValues=\z@ -\PerChar{\ActionPerChar}{#1}} - -% To draw a plot of the number of occurrences of the characters of a sentence -\def\DrawOccurrences#1{% -\StatSentence{#1} -% -\pst@cnta=\AssociativeArrayNbValues -\advance\pst@cnta\@ne -% -% To know the maximum of the numbers -\pst@cntb=\z@ -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Values(\iValue)% - \ifnum\cachedata>\pst@cntb - \pst@cntb=\cachedata - \fi} -\advance\pst@cntb\@ne -% -% The drawing itself -\pspicture(-0.5,-0.5)(\pst@cnta,\pst@cntb) - \psaxes[axesstyle=frame,labels=y](\pst@cnta,\pst@cntb) - \multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \Draw@OneOccurrence{\iValue}} -\endpspicture} - -% To draw the value for one occurrence -\def\Draw@OneOccurrence#1{% -\checkAssociativeArray@Values(#1)% -\psdot(#1,\cachedata) -\rput[B](\iValue,-0.5){\AssociativeArray@Names(#1)}} - -\let\Names\AssociativeArray -\let\checkNames\checkAssociativeArray - -\psset{dotstyle=o,dotsize=0.4} - -\makeatother - -\vspace{8mm} % Poor hack to force a page break... - We will now write another version, using another array to store indexes, -to allow us to sort the letters found in the sentence read. - -\begin{CenterExample} - \makeatletter - - % /HLComment?To get in #2 the ASCII code of the #1 character; - /HLMacro?\def\Character@AsciiCode;#1#2{\chardef#2=`#1\relax} - - % /HLComment?A new "standard" array to store the sorted indexes; - \newarray\AssociativeArray@Indexes - - % /HLComment?A simple macro to print the array of indexes (for debugging); - /HLMacro?\def\PrintIndexes;{% - \multido{\iIndexes=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Indexes(\iIndexes)% - \BS\texttt{indexes(\iIndexes)}=`\cachedata'\space}} - - % /HLComment?We redefine the macro to store an element in the associative array,; - % /HLComment?to allow to sort it elements, using an additional array of indexes; - /HLMacro?\def\AssociativeArray;(#1)=#2{% - \expandarrayelementtrue - \AssociativeArray@ElementFoundfalse - \edef\@tempa{#1}% - \edef\@tempb{#2}% - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % /HLComment?This element already exist: we replace it current value; - % /HLComment?\checkAssociativeArray@Values(\iValue)% Debug; - % /HLComment?\typeout{In #1, replace `\cachedata'\space by `#2'}% Debug; - \AssociativeArray@Values(\iValue)={\@tempb}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} - \ifAssociativeArray@ElementFound - \else - % /HLComment?New element: we must insert it at it sorted position; - \@tempcnta=\@ne - \expandafter\Character@AsciiCode\@tempa\@tempx - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \expandafter\Character@AsciiCode\cachedata\@tempy - \ifnum\@tempx<\@tempy - % /HLComment?The new element must be before this one: we will exchange their values; - \checkAssociativeArray@Indexes(\iValue)% - \@tempcntb=\cachedata - \advance\@tempcntb\@ne - \AssociativeArray@Indexes(\iValue)={\the\@tempcntb}% - \else - \advance\@tempcnta\@ne - \fi} - % - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={\@tempa}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={\@tempb}% - \AssociativeArray@Indexes(\AssociativeArrayNbValues)={\the\@tempcnta}% - \fi} - - % /HLComment?We change the way we draw each number of occurrences; - /HLMacro?\def\Draw@OneOccurrence;#1{% - \checkAssociativeArray@Indexes(#1)% - \pst@cnta=\cachedata - \checkAssociativeArray@Values(#1)% - \psdot(\the\pst@cnta,\cachedata) - \rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \DrawOccurrences{We are Wednesday} - - \PrintIndexes -\end{CenterExample} - -\makeatletter - -% To get in #2 the ASCII code of the #1 character -\def\Character@AsciiCode#1#2{\chardef#2=`#1\relax}% - -% A new "standard" array to store the sorted indexes -\newarray\AssociativeArray@Indexes - -% We redefine the macro to store an element in the associative array, -% to allow to sort it elements, using an additional array of indexes -\def\AssociativeArray(#1)=#2{% -\expandarrayelementtrue -\AssociativeArray@ElementFoundfalse -\edef\@tempa{#1}% -\edef\@tempb{#2}% -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % This element already exist: we replace it current value - % \checkAssociativeArray@Values(\iValue)% Debug - % \typeout{In #1, replace `\cachedata'\space by `#2'}% Debug - \AssociativeArray@Values(\iValue)={\@tempb}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} -\ifAssociativeArray@ElementFound -\else - % New element: we must insert it at it sorted position - \@tempcnta=\@ne - \expandafter\Character@AsciiCode\@tempa\@tempx - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \expandafter\Character@AsciiCode\cachedata\@tempy - \ifnum\@tempx<\@tempy - % The new element must be before this one: we will exchange their values - \checkAssociativeArray@Indexes(\iValue)% - \@tempcntb=\cachedata - \advance\@tempcntb\@ne - \AssociativeArray@Indexes(\iValue)={\the\@tempcntb}% - \else - \advance\@tempcnta\@ne - \fi} - % - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={\@tempa}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={\@tempb}% - \AssociativeArray@Indexes(\AssociativeArrayNbValues)={\the\@tempcnta}% -\fi} - -% We change the way we draw each number of occurrences -\def\Draw@OneOccurrence#1{% -\checkAssociativeArray@Indexes(#1)% -\pst@cnta=\cachedata -\checkAssociativeArray@Values(#1)% -\psdot(\the\pst@cnta,\cachedata) -\rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - -\makeatother - -\begin{CenterExample} - \DrawOccurrences{Tuesday 8 February} -\end{CenterExample} - -\noindent Now, we can easily redefine the internal macro which plot each -occurrence, to obtain various kinds of graphics: - -\begin{CenterExample} - \makeatletter - - /HLMacro?\def\Draw@OneOccurrence;#1{% - \checkAssociativeArray@Indexes(#1)% - \pst@cnta=\cachedata - \checkAssociativeArray@Values(#1) - \psline[linestyle=dotted](\the\pst@cnta,0)(\the\pst@cnta,\cachedata) - \psdot(\the\pst@cnta,\cachedata) - \rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \psset{xunit=0.5,dotstyle=*,dotsize=0.3} - \DrawOccurrences{I do not believe that it can be correct} -\end{CenterExample} - -\begin{CenterExample} - \makeatletter - - \SpecialCoor - - /HLMacro?\def\Draw@OneOccurrence;#1{% - \checkAssociativeArray@Indexes(#1)% - \pst@cnta=\cachedata - \checkAssociativeArray@Values(#1)% - \pspolygon*[linecolor=red](! \the\pst@cnta\space 0.3 sub 0) - (! \the\pst@cnta\space 0.3 sub \cachedata) - (! \the\pst@cnta\space 0.3 add \cachedata) - (! \the\pst@cnta\space 0.3 add 0) - \rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \psset{xunit=0.5,ticks=y} - \DrawOccurrences{I don't know a better solution than this one} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\section{Thanks} - - I would like to thank Rolf Niepraschk \verb+<niepraschk@ptb.de>+ to have -carefully read a preliminary version of this document and to have sent me -several good advices to clarify and improve some points. - -\begin{thebibliography}{9} - \bibitem{SVB93} Stephan von \textsc{Bechtolsheim}, \emph{\TeX{} in - Practice}, four volumes, Springer-Verlag, New York, 1993 (see also - \url{CTAN: macros/tip/arraymac.tip}). - \bibitem{REPEAT} \RepeatPackage, by Victor \textsc{Eijkhout}, University of - Illinois, Urbana-Champaign, USA, \url{CTAN: macros/generic/eijkhout/repeat} - \bibitem{EG98} Philippe \textsc{Esperet} and Denis \textsc{Girou}, - \emph{Coloriage du pavage dit de Truchet}, Cahiers GUTenberg, Number~31, - December 98, pages 5-18, in french (see - \url{http://www.gutenberg.eu.org/pub/GUTenberg/publicationsPS/31-girou.ps.gz}). - \bibitem{ALDRATEX} \AlDraTeXPackage, by Eitan M. \textsc{Gurari}, Ohio State - University, Columbus, USA, \url{CTAN: graphics/dratex} (see also - \url{http://www.cis.ohio-state.edu/~gurari/systems.html}). - \bibitem{Gur94} Eitan M. \textsc{Gurari}, \emph{\TeX{} and \LaTeX: Drawing - and Literate Programming}, McGraw-Hill, New-York, 1994. - \bibitem{METAPOST} \MetaPostPackage, by John D. \textsc{Hobby}, AT\&T Bell - Laboratories, USA, \url{CTAN: graphics/metapost} (see also - \url{http://cm.bell-labs.com/who/hobby/MetaPost.html}). - \bibitem{FORMLETT} \FormLettPackage, by Zhuhan \textsc{Jiang}, University of - New England, Armidale, Australia, \url{CTAN: macros/generic/formlett.sty} (see - also \url{http://maths.une.edu.au/~zhuhan/util.html#computer}). - \bibitem{MULTIDO} \MultiDoPackage, by Timothy van \textsc{Zandt}, INSEAD, - Fontainebleau, France, \url{CTAN: macros/generic/multido} - \bibitem{PSTRICKS} \PSTricksPackage, by Timothy van \textsc{Zandt}, INSEAD, - Fontainebleau, France, \url{CTAN: graphics/pstricks} (see also - \url{http://www.tug.org/applications/PSTricks}). -\end{thebibliography} - -\end{document} diff --git a/Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.pdf b/Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.pdf Binary files differdeleted file mode 100644 index 25699278ee5..00000000000 --- a/Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.pdf +++ /dev/null diff --git a/Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.tex b/Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.tex deleted file mode 100644 index 0dbd380f55d..00000000000 --- a/Master/texmf-dist/tex/generic/arrayjobx/arrayjobx.tex +++ /dev/null @@ -1,2096 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% arrayjobx.tex --- Documentation of the `arrayjobx' package from Zhuhan Jiang -%% -%% Author : Denis GIROU (CNRS/IDRIS - France) <Denis.Girou@idris.fr> -%% Created the : Fri Jan 7 21:13:20 2000 -%% Last mod. by : Michael Sharpe (UCSD - USA) <msharpe@ucsd.edu> -%% Last mod. the : Mon May 3 11:18:300 2010 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\documentclass{article} - -\usepackage{arrayjobx} % Arrays management -\usepackage{fancyvrb} % Fancy verbatims -\usepackage[width=18cm]{geometry} % Page layout -\usepackage{graphics} % Graphics LaTeX standard package -\usepackage{ifthen} % Convenient conditionals in LaTeX -\usepackage{mflogo} % For the MetaFont and MetaPost logos -\usepackage{multido} % General loop macro -\usepackage{url} % URLs convenient typesetting - -% For PSTricks examples -\newif\ifpstricks -\IfFileExists{pstricks.sty}{% -\pstrickstrue -%\usepackage{pstcol} % PSTricks package with `color' interface -\usepackage{pst-node} % PSTricks nodes package -\usepackage{pst-plot} % PSTricks plots package -\usepackage{pst-grad} % PSTricks gradients package -%\usepackage{pst-key} % PSTricks interface to the `keyval' package -}{% -\usepackage{color} -} % Color LaTeX standard package - -% Definition of new colors -\definecolor{Khaki} {rgb}{0.94,0.90,0.55} -\definecolor{LemonChiffon}{rgb}{1.,0.98,0.8} - -% A unique string for TeX and LaTeX -\newcommand{\AllTeX}{% -{\rm(L\kern-.36em\raise.3ex\hbox{\sc a}\kern-.15em)% -T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}} - -% Package names -\newcommand{\AlDraTeXPackage}{\textsf{(Al)Dra\TeX}} -\newcommand{\ArrayJobPackage}{`\textsf{arrayjobx}'} -\newcommand{\FormLettPackage}{`\textsf{formlett}'} -\newcommand{\IfThenPackage}{`\textsf{ifthen}'} -\newcommand{\MetaFontPackage}{\MF} -\newcommand{\MetaPostPackage}{\MP} -\newcommand{\MultiDoPackage}{`\textsf{multido}'} -\newcommand{\PSTricksPackage}{\textsf{PSTricks}} -\newcommand{\RepeatPackage}{`\textsf{repeat}'} - -% Aligned labels in a description environment -\newenvironment{Description}[1]{% -\begin{list}{nothing}{\setlength{\leftmargin}{#1} -\setlength{\labelwidth}{\leftmargin}\setlength{\labelsep}{1mm}}} -{\end{list}} - -% If PSTricks is not available -\newcommand{\PSTricksExampleNotShown}{% -\vspace{2mm} -\centerline{\fbox{\textbf{Example not shown here because PSTricks is not - available on this platform.}}}} - -% Character to define verbatim strings, with escape characters /?; (from `fancyvrb') -\DefineShortVerb[commandchars=/?;]{\!} - -\VerbatimFootnotes % Allow verbatim material in footnotes (from `fancyvrb') - -% Some advices from Rolf Niepraschk -\newcommand{\BS}{\texttt{\symbol{`\\}}} -\newcommand{\Macro}[1]{\texttt{\BS#1}} -\newcommand{\Variable}[1]{\textnormal{\textit{\(\langle\)#1\,\(\rangle\)}}} -\newcommand{\Parameter}[1]{\texttt{\symbol{`\{}#1\symbol{`\}}}} - -% To format TeX macro strings -\newcommand{\FormatTeXMacro}[1]{\Macro{#1}\hfill :} - -\makeatletter - -% Example environments -% (do not use in them the /?; characters, that we will be used as escape characters!) - -% For highlighting some verbatim sequences (array names, macro names and comments) -\def\HLReverse#1{{% -\setlength{\fboxsep}{1pt}% -\colorbox{black}{\textcolor{white}{\textbf{#1}}}}} -\def\HLMacro#1{\BS{}def\HLMacro@i#1\@nil} -\def\HLMacro@i#1def#2\@nil{{% -\setlength{\fboxsep}{1pt}% -\colorbox{black}{\textcolor{white}{\textbf{#2}}}}} -\def\HLComment#1{\textit{#1}} - -\def\Example{\FV@Environment{}{Example}} -\def\endExample{% -\end{VerbatimOut} -\Below@Example{\input{\jobname.tmp}} -\endgroup} - -\def\CenterExample{\FV@Environment{}{Example}} -\def\endCenterExample{% -\end{VerbatimOut}% -\begin{center} -\Below@Example{\input{\jobname.tmp}} -\end{center} -\endgroup} - -\def\SideBySideExample{\FV@Environment{}{Example}} -\def\endSideBySideExample{% -\end{VerbatimOut}% -\SideBySide@Example{\input{\jobname.tmp}} -\endgroup} - -\def\FVB@Example{% -\begingroup -\FV@UseKeyValues -\parindent=0pt -\multiply\topsep by 2 -\VerbatimEnvironment -\begin{VerbatimOut}[codes={\catcode`\Z=12}]{\jobname.tmp}} - -\def\Below@Example#1{% -\VerbatimInput[gobble=0,commentchar=Z,commandchars=/?;,numbersep=3pt, - frame=single,numbers=left]% - {\jobname.tmp} -\catcode`\Z=9\relax% -% We suppress the effect of the highlighting macros -\catcode`/=0\relax% -\catcode`?=1\relax% -\catcode`;=2\relax% -\def\HLReverse##1{##1}% -\def\HLMacro##1{##1}% -\def\HLComment##1{##1}% -#1\par} - -\def\SideBySide@Example#1{% -\@tempdimb=\FV@XRightMargin -\advance\@tempdimb -5mm -\begin{minipage}[c]{\@tempdimb} - \fvset{xrightmargin=0pt} - \catcode`\Z=9\relax% - % We suppress the effect of the highlighting macros - \catcode`/=0\relax% - \catcode`?=1\relax% - \catcode`;=2\relax% - \def\HLReverse##1{##1}% - \def\HLMacro##1{##1}% - \def\HLComment##1{##1}% - #1 -\end{minipage}% -\@tempdimb=\textwidth -\advance\@tempdimb -\FV@XRightMargin -\advance\@tempdimb 5mm -\begin{minipage}[c]{\@tempdimb} - \VerbatimInput[gobble=0,commentchar=Z,commandchars=/?;, - numbersep=3pt,frame=single,numbers=left, - xleftmargin=5mm,xrightmargin=0pt]{\jobname.tmp} -\end{minipage}} - -\makeatother - -% Source codes must be indented by 2 spaces -\fvset{gobble=2,frame=single,numbers=left,numbersep=1mm} - -\begin{document} - -\title{The \ArrayJobPackage{} package\\Management of arrays in \AllTeX} -\author{Zhuhan Jiang\\School of Computing and Mathematics\\ - University of Western Sydney\\Sydney\\Australia\\ - {\footnotesize email: zhuhan@scm.uws.edu.au}\\[5mm] - {\footnotesize (Documentation: Denis Girou% - \footnote{All errors and misunderstandings are mine.} - \hspace{1mm}(CNRS/IDRIS -- France) -- - Denis.Girou@idris.fr)}} -\date{Version 1.04\\May 3, 2010\\ - {\small Documentation revised May 31, 2000, edited lightly May 3, 2010 by Michael Sharpe}} - -\maketitle - -\begin{abstract} - This package provides array data structures in \AllTeX, in the meaning of -the classical procedural programming languages like Fortran, Ada or C, and -macros to manipulate them. Arrays can be mono or bi-dimensional. - - This is useful for applications which require high level programming -techniques, like algorithmic graphics programmed in \TeX. This version no longer conflicts with some macros in the {\tt amsmath} package. It should be used for all new work. -\end{abstract} - -\tableofcontents - -\section{Introduction} - - One of the big advantages of the \AllTeX{} system over common interactive -software for text processing is that it offer, also, a programming language, -which give, to people who have some knowledge in the algorithmic and -programming fields, an exceptional flexibility and power. - - Nevertheless, \TeX{} is a rather specific programming language, based on -macro expansion, which implements a lot of unusual constructs but lacks some that are very familiar in the classical procedural languages, as -\emph{arrays} to store and retrieve arbitrary pieces of data, stored in a -structured way. The main reason why they were not integrated in \TeX{} was -perhaps that arrays did not seem very useful in a language focussed on text processing (but -\MetaFontPackage{}, for instance, does has them). Nevertheless, one of the few -applications where this is straightforward to use them is to program a mailing -system, where nearly the same information is to be formatted several times, -depending of values which can be simply retrieved from an array of data. This -was the goal of the \FormLettPackage{} package \cite{FORMLETT}, written in -1993-1995 by Zhuhan Jiang for dealing with mass letters, invoices and similar -tasks of some duplicative nature. It implemented a small but powerful set of -macros to manage arrays, which have been extracted to form the present -\ArrayJobPackage{} package. The arrays can be mono or bi-dimensional% -\footnote{You can use more than two dimensions, but not in the meaning of the -classical programming languages (see page \pageref{par:DataHeight})} -and they are dynamically allocated (so we do not have to declare their -dimension statically.)% -\footnote{Stephan von Bechtolsheim \cite[Volume \textsc{III}, paragraph 20.3, -page 136]{SVB93} also demonstrated such macros for array management in the -third volume of his huge book, but it was limited to mono-dimensional -arrays.}. - - Array structures are, at the opposite of text management, often very useful -in graphic programming. This is why the \AlDraTeXPackage{} package from Eitan -Gurari \cite{ALDRATEX} (see also \cite{Gur94}) integrate such functionality -(but which is bundled inside this package and could not be extracted easily -from it), and this is also the case for the \MetaPostPackage{} package -\cite{METAPOST} (but this one do not use \TeX{} as programming language)% -\footnote{Another required feature, used in conjunction with the managements -of arrays, is a generic loop mechanism. \TeX{} offer the \Macro{loop} macro -and \LaTeX{} the \Macro{whiledo} macro of the \IfThenPackage{} package (and -also the internal \Macro{@for}, \Macro{@whilenum}, etc. macros), but a more -high-level structure is to be preferred, as the ones defined too in the -\AlDraTeXPackage{} or \MetaPostPackage{} packages. We will use in our examples -the \MultiDoPackage{} package \cite{MULTIDO}, also written by Timothy van -Zandt, but others are available, like the \RepeatPackage{} package written by -Victor Eijkhout \cite{REPEAT}.}. This fact explain why most of our examples in -this documentation will concern the area of \emph{graphic programming} (here -using the \PSTricksPackage{} package from Timothy van Zandt \cite{PSTRICKS}). - -\section{Command reference} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{newarray}] Define a new array. - - Syntax: !\newarray/Macro?/Variable?ArrayName;;! - - Example: !\newarray\Values! - - \item[\FormatTeXMacro{delarray}] Delete an array. - - Syntax: !\delarray/Macro?/Variable?ArrayName;;! - - Example: !\delarray\Values! - - Remarks: - \begin{enumerate} - \item obviously, elements of a deleted array could not be accessed - later, - \item take care that the elements of a deleted array are not - themselves deleted.\newline - So, \verb+\delarray\Data \newarray\Data \Data(I)+ can produce - strange behavior. Just avoid reusing deleted arrays. - \end{enumerate} - - \item[\FormatTeXMacro{ArrayName}] Store or get the content of the array - element specified by the index/indices. In the last case, the content is - inserted at the current point. - - Syntax: !/Macro?/Variable?ArrayName;;(I)=/Parameter?/Variable?Content;;! or more - generally\newline - \hspace*{1.3cm}!/Macro?/Variable?ArrayName;;(I1,...,In)=/Parameter?/Variable?Content;;! - to store a value - - \hspace{1.3cm}!/Macro?/Variable?ArrayName;;(I)! or more generally - !/Macro?/Variable?ArrayName;;(I1,...,In)! to retrieve a value - - Examples: !\Data(6)={Paul Adams}! - - \hspace{1.75cm}!\Values(19)! - - \item[\FormatTeXMacro{readarray}] Store consecutive values in an array, - starting from the indice one. - - Syntax: !\readarray/Parameter?/Variable?ArrayName;;=/Parameter?/Variable?Content1;&...&/Variable?ContentM;;! - - Example: !\readarray{Actors}{Louise Brooks&Marlene Dietrich&Clark Gable}! - - Remarks: - \begin{enumerate} - \item the values must be separated by the \textbf{\&} character, - \item take care that the trailing spaces are significant, so the - previous definition is different from the following one: - - !\readarray{Actors}{Louise Brooks & Marlene Dietrich & Clark Gable}! - \item you can use \AllTeX{} macros inside the values. - \end{enumerate} -\end{Description} - -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Values - \readarray{/HLReverse?Values;}{A&B&C&D} - \verb+\Values(3)+ = `\Values(3)' - \newarray\Actors - \readarray{/HLReverse?Actors;}{Louise Brooks&Marlene Dietrich&Clark Gable} - Z\par - \verb+\Actors(2)+ = `\Actors(2)' - \readarray{/HLReverse?Actors;}{% - Louise Brooks & Marlene Dietrich & Clark Gable} - Z\par - \verb+\Actors(2)+ = `\Actors(2)' - \Actors(4)={\textit{\underline{Ida Lupino}}} - Z\par - \verb+\Actors(4)+ = `\Actors(4)' -\end{SideBySideExample} - -\vspace{3mm} -\noindent If you really need to trim the unnecessary left and right spaces, you must -apply a special action, like this one: - -\begin{Example} - \def\BS{\texttt{\symbol{`\\}}} - - \newarray\Strings - \readarray{/HLReverse?Strings;}{a& b&c c & d dd ddd } - - \multido{\iString=1+1}{4}{% - \checkStrings(\iString)% - \BS\texttt{Strings(\iString)}=`\cachedata'\qquad} - - \makeatletter - - % /HLComment?A \TrimSpaces macro adapted from Michael J. Downes <epsmjd@ams.org>; - % /HLComment?(posted on c.t.t. June 19, 1998); - % /HLComment?\number`\x reads past one following space (expanding as it goes); - \long\def\TrimSpaces#1{\expandafter\TrimSpaces@i\number`\^^00#1| |} - % /HLComment?Remove the "0" produced by \number`\^^00, and " |" at the end.; - \long\def\TrimSpaces@i 0#1 |{\TrimSpaces@ii\empty#1|} - % /HLComment?" |" was removed by \TrimSpaces@i, now remove a trailing "||" or "| |"; - \long\def\TrimSpaces@ii #1|#2|{#1} - - \makeatother - - \multido{\iString=1+1}{4}{% - \checkStrings(\iString)% - \BS\texttt{Strings(\iString)}=`\TrimSpaces{\cachedata}'\qquad} -\end{Example} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{check}] Get the content of the array element specified - by the indice(s) and store the result in the macro !\cachedata! - - Syntax: !\check/Variable?ArrayName;(I)! or more generally - !\check/Variable?ArrayName;(I1,..,In)! - - Example: !\checkActors(2)! - \item[\FormatTeXMacro{cachedata}] Macro where the content is stored after - a !\check! request. - \item[\FormatTeXMacro{ifemptydata}] True if the last \Macro{check} request - has given an empty result. -\end{Description} - -\newarray\Values -\readarray{Values}{A&B&C&D} - -\newarray\Actors -\newarray\Dates -\newarray\Sexes -\readarray{Actors}{Louise Brooks&% - Marlene Dietrich&% - Clark Gable} -\readarray{Dates}{1906--1985&% - 1902--1992&% - 1901--1960} -\readarray{Sexes}{2&2&1} - -\begin{SideBySideExample}[xrightmargin=6cm] - % /HLComment?Plain TeX usage; - \checkValues(2)% - \verb+\Values(2)+ = `\cachedata' - Z\par - \checkActors(3)% - \verb+\Actors(3)+ = `\cachedata' - Z\par - \checkActors(5)% - \ifemptydata - \verb+\Actors(5)+ not defined. - \fi - Z\par - % /HLComment?LaTeX usage; - \newcommand{\IsEmptyElement}[2]{% - \ifthenelse{\boolean{emptydata}}{#1}{#2}} - \checkActors(3)% - \verb+\Actors(3)+ = \IsEmptyElement{not defined}{`\cachedata'} - Z\par - \checkActors(5)% - \verb+\Actors(5)+ \IsEmptyElement{not defined}{`\cachedata'} -\end{SideBySideExample} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{ifnormalindex}] See below (Default: !\normalindexfalse!). - - \item[\FormatTeXMacro{dataheight}\label{par:DataHeight}] Counter containing - the number of elements in the first dimension, if arrays are bi-dimensional. - - Syntax: !\dataheight=/Variable?Number;! - - Remarks: - \begin{enumerate} - \item arrays are monodimensional when !\dataheight!~$\leq~1$, - \item if !\normalindexfalse! (which is the default value), we have: - $$\hspace{-3cm}\Macro{\Variable{ArrayName}}(I_1,...,I_n) - = \Macro{\Variable{ArrayName}}(I_n + (I_{n-1}-1) * - \Macro{dataheight} + \cdots - + (I_1-1) * \Macro{dataheight}^{n-1})$$ - - and if !\normalindextrue!, we have: - $$\hspace{-3cm}\Macro{\Variable{ArrayName}}(I_1,...,I_n) - = \Macro{\Variable{ArrayName}}(I_1 + (I_2-1) * - \Macro{dataheight} + \cdots - + (I_n-1) * \Macro{dataheight}^{n-1})$$ - \end{enumerate} -\end{Description} - -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Letters - \readarray{/HLReverse?Letters;}{A&B&C&D&E&F&G&H&I&J} - \dataheight=5 - - Z\begin{tabular}{c|c|c|c|c|c|c|c|c|} - Z \multicolumn{1}{c}{} & \multicolumn{1}{c}{1} & \multicolumn{1}{c}{2} & - Z \multicolumn{1}{c}{3} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{5} \\ \cline{2-6} - Z 1 & A & B & C & D & E \\ \cline{2-6} - Z 2 & F & G & H & I & J \\ \cline{2-6} - Z\end{tabular} - Z\\[2mm] - % /HLComment?Default is \normalindexfalse; - \verb+\Letters(1,2)=+`\Letters(1,2)' - Z\par - \verb+\Letters(2,1)=+`\Letters(2,1)' - Z\\[2mm] - Z\begin{tabular}{c|c|c|} - Z \multicolumn{1}{c}{} & \multicolumn{1}{c}{1} & \multicolumn{1}{c}{2} \\ \cline{2-3} - Z 1 & A & F \\ \cline{2-3} - Z 2 & B & G \\ \cline{2-3} - Z 3 & C & H \\ \cline{2-3} - Z 4 & D & I \\ \cline{2-3} - Z 5 & E & J \\ \cline{2-3} - Z\end{tabular} - Z\\[2mm] - \normalindextrue - \verb+\Letters(1,2)=+`\Letters(1,2)' - Z\par - \verb+\Letters(2,1)=+`\Letters(2,1)' -\end{SideBySideExample} - -\begin{Description}{4cm} - \item[\FormatTeXMacro{ifexpandarrayelement}] Boolean macro to allow or not - the element to be evaluated before to be stored in the array (Default: - !\expandarrayelementfalse!). - - Syntax: !\expandarrayelementtrue! or !\expandarrayelementfalse! - - Remark: take care to the possible side effects if you store some macros - as values of some array elements without evaluating them, as they can - change of content later... (see the following examples). -\end{Description} - -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Data - \newcount\CounterP % /HLComment?Plain TeX usage; - \CounterP=3 - \newcounter{CounterL} % /HLComment?LaTeX usage; - \setcounter{CounterL}{3} - \def\Town{Madrid} - \Data(1)={\the\CounterP} - \Data(2)={\the\value{CounterL}} - \Data(3)={\Town} - - \expandarrayelementtrue - \Data(4)={\the\CounterP} - \Data(5)={\the\value{CounterL}} - \Data(6)={\Town} - - \CounterP=5 - \setcounter{CounterL}{5} - \def\Town{Roma} - - \multido{\iData=1+1}{6}{% - \BS\texttt{Data(\iData)}=`\Data(\iData)'\\} -\end{SideBySideExample} - -\vspace{3mm} -\noindent Some other macros exists for mono-dimensional arrays (and only for -them), but have little additional interest: - -\begin{Description}{4cm} - \item[\FormatTeXMacro{arrayx}] Store or get the content of the array element - specified by the index. In the last case, the content is inserted at the - current point.\footnote{The macro name \verb|\array| conflicted with macros in {\tt amsmath}, and is changed as of version 1.04. (Modification suggested by Michael Sharpe.)} - - Syntax: !\arrayx/Parameter?/Variable?ArrayName;;(I)=/Parameter?/Variable?Content;;! - to store a value - - \hspace{1.3cm}!\arrayx/Parameter?/Variable?ArrayName;;(I)! to retrieve a value - - Examples: !\arrayx{Actors}(6)={Joan Crawford}! - - \hspace{1.75cm}!\arrayx{Actors}(3)! - - \item[\FormatTeXMacro{clrarray}] Clear the content of the array element specified. - A following inquiry on this element will give an empty content. - - Syntax: !\clrarray/Parameter?/Variable?ArrayName;;(I)! - - Example: !\clrarray{Actors}(2)! - - \item[\FormatTeXMacro{testarray}] Get the content of the array element specified - by the index and store the result in the macro !\temp@macro!% - \footnote{In \LaTeX, this macro should be used inside a package or between - the \verb+\makeatletter+ $\cdots$ \verb+\makeatother+ macro pair.}. - - Syntax: !\testarray/Parameter?/Variable?ArrayName;;(I)! - - Example: !\testarray{Actors}(1)\typeout{Actors(1)=`\temp@macro'}! -\end{Description} - -\section{Examples} - -\UndefineShortVerb{\!} % We will use the ! character in the next examples - - We will first show some basic and easy examples, before looking at more -advanced ones to solve some complex problems, which require more knowledge of -\TeX{} programming techniques. - -\subsection{Basic examples} - - The immediate thing for which we can use arrays is to store and retrieve -information: - -\vspace{2mm} -\begin{SideBySideExample}[xrightmargin=6cm] - \newarray\Actors - \newarray\Dates - \newarray\Sexes - - \readarray{/HLReverse?Actors;}{Louise Brooks&Marlene Dietrich&Clark Gable} - \readarray{/HLReverse?Dates;}{1906--1985&1902--1992&1901--1960} - \readarray{/HLReverse?Sexes;}{2&2&1} - - \begin{description} - \item[\Actors(1)] : \Dates(1) - \item[\Actors(2)] : \Dates(2) - \item[\Actors(3)] : \Dates(3) - \end{description} -\end{SideBySideExample} - -\vspace{2mm} - But we can also use a general loop macro, as the one provided by the -\MultiDoPackage{} package, for more powerful usage and a management -independent of the number of elements: - -\vspace{2mm} -\begin{SideBySideExample}[xrightmargin=6cm] - \newcommand{\NumberActors}{3} - - \begin{description} - \multido{\iActor=1+1}{\NumberActors}{% - \item[\Actors(\iActor)] : \Dates(\iActor)} - \end{description} -\end{SideBySideExample} - -\vspace{2mm} - This allow various usage in the formatting of texts. A common usage is for a -\emph{mailing} process, when we must compose some similar letters to various -people (as we said previously, this was the reason for which these macros were -developed in the \FormLettPackage{} package). Here, the usage of a programming -language allow a great flexibility, using some conditionals to format the text -differently or even to insert different pieces of text according to the person: - -\newcommand{\NumberActors}{3} - -\begin{CenterExample} - \newcounter{iActor} - - \newcommand{\AccordingSexe}[2]{% - \checkSexes(\the\value{iActor})% - \ifthenelse{\equal{\cachedata}{1}}{#1}{#2}} - - \whiledo{\value{iActor} < \NumberActors}{% - \stepcounter{iActor}% - \fbox{% - \begin{minipage}{0.985\textwidth} - Dear \AccordingSexe{Mr}{Mrs} \Actors(\the\value{iActor}), - - I would like to tell you how I admire the great \AccordingSexe{actor}{actress} - you are, etc. - \end{minipage}}\\[5mm]} -\end{CenterExample} - - Nevertheless, people who know a little \TeX{} as a programming language know -that it behaviour is full of pitfalls... For instance, the following example, -which format a table according to the content of entries stored in external -arrays, can't work: - -\begin{Verbatim} - \begin{tabular}{|l|c|} - \hline - \multicolumn{1}{|c}{\textbf{Actors}} & \multicolumn{1}{|c|}{\textbf{Dates}} \\ \hline - \multido{\iActor=1+1}{\NumberActors}{\Actors(\iActor) & \Dates(\iActor) \\ \hline} - \end{tabular} -\end{Verbatim} - - This is because there is an implicit grouping of each entry in a tabular -environment and that it do not work with the grouping of the \verb+\multido+ -loop. So, this must be program in a different way, storing all the content of -the table before really inserting it: - -\begin{SideBySideExample}[xrightmargin=6cm,baselinestretch=0.9] - \begin{tabular}{|l|c|} - \hline - \multicolumn{1}{|c}{\textbf{Actors}} & - \multicolumn{1}{|c|}{\textbf{Dates}} \\ \hline - \let\ListActors\empty - \begingroup - \let\Actors\relax - \let\Dates\relax - \let\\\relax - \let\hline\relax - \multido{\iActor=1+1}{\NumberActors}{% - \xdef\ListActors{\ListActors - \Actors(\iActor) & \Dates(\iActor) \\ \hline}} - \endgroup - \ListActors - \end{tabular} -\end{SideBySideExample} - -\subsubsection{Plot labels} - - A basic usage in graphic programming is to use arrays to retrieve the labels -to put on a drawing, as here to label the simple plot below. (Note the change from the original documentation. The axis labels used with \verb|\psaxes| must now be numeric, so it is necessary to bypass the automatic axis labeling.) -\ifpstricks % If PSTricks is available -\begin{CenterExample}[baselinestretch=0.9] - \savedata{\Data}[(1,3)(2,1)(3,2)(4,1)(5,1)(6,3),(7,2)(8,1)(9,3)(10,3)(11,1)(12,1)] - - \newcommand{\PlotData}[1]{% - \begin{pspicture}(-0.5,-0.5)(13,4) - \psaxes[labels=none]{->}(13,4) - \dataplot[plotstyle=dots,dotstyle=o,dotsize=0.3]{\Data} - #1\end{pspicture}} - \PlotData{\psaxes[showorigin=false]{->}(13,4)} - - \newarray{\Months} - \readarray{/HLReverse?Months;}{January&February&March&April&May&June&July&August&September&% - October&November&December} - \newarray{\Levels} - \readarray{/HLReverse?Levels;}{Low&Medium&High} - %\renewcommand{\pshlabel}[1]{\tiny\Months(#1)} - \PlotData{\psaxes[labels=y,showorigin=false]{->}(13,4)% - \multido{\i=1+1}{12}{\rput[B](\i,-12pt){\tiny\Months(\i)}}} - - %\renewcommand{\psvlabel}[1]{\small\Levels(#1)} - \PlotData{\multido{\i=1+1}{12}{\rput[B](\i,-12pt){\tiny\Months(\i)}}% - \multido{\i=1+1}{3}{\rput[r](-12pt,\i){\small\Levels(\i)}}} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\subsubsection{Checkboard drawing} - - Of course, a bi-dimensional array directly allow to store the state of a -checkboard of one of the numerous ones existing, like the reversi game that -we will show here (in fact, the only more difficult part to understand in this -example concern the definition of the elementary piece, but as this is not -related at all to the usage of \ArrayJobPackage, this point can be forgotten -by most of the readers). - -\ifpstricks % If PSTricks is available -\begin{SideBySideExample}[xrightmargin=6cm,baselinestretch=0.89] - /HLMacro?\def\Black;{B} - /HLMacro?\def\White;{W} - - /HLMacro?\def\Piece;#1#2{{% - \psset{unit=0.8}% - \pspicture(0,-0.1)(1,0.8) - \pscustom[fillstyle=gradient,gradmidpoint=0,gradangle=90, - gradbegin=#2,gradend=#1]{% - \psbezier(0,0.2)(0.1,-0.2)(0.9,-0.2)(1,0.2) - \psline(1,0.2)(1,0.5) - \psbezier(1,0.5)(0.9,0.9)(0.1,0.9)(0,0.5) - \psline(0,0.5)(0,0.2)} - \psbezier(0,0.5)(0.1,0.1)(0.9,0.1)(1,0.5) - \endpspicture}} - - /HLMacro?\def\PieceBlack;{\Piece{black}{gray}} - /HLMacro?\def\PieceWhite;{\Piece{white}{gray}} - - /HLMacro?\def\CheckboardHook;{} - - \newarray\Checkboard - - /HLMacro?\def\ShowCheckboard;{% - \dataheight=8 - \pspicture(8,8) - \psgrid[subgriddiv=0,gridlabels=0](8,8) - \CheckboardHook - \multido{\iColumn=1+1,\iColumnPos=0+1}{8}{% - \multido{\iRow=1+1,\iRowPos=7+-1}{8}{% - \checkCheckboard(\iRow,\iColumn)% - \ifx\cachedata\Black - \rput(\iColumnPos.5,\iRowPos.5){\PieceBlack} - \else - \ifx\cachedata\White - \rput(\iColumnPos.5,\iRowPos.5){\PieceWhite} - \fi - \fi}} - \endpspicture} - - \readarray{/HLReverse?Checkboard;}{% - W& &B& & & & &B&% - &W&B& & & & &B&% - W&W&B& &W& & &B&% - W&W&B&W&W&W&B&B&% - B& &W&W&W&B&W&B&% - B&B&W&W&W&B&W&B&% - B&B&B&W&W&W&W&B&% - W&B&B&B&B&B&B&B&% - } - - \psset{unit=0.6} - \ShowCheckboard - - \Checkboard(2,1)={B} % /HLComment?Black move; - /HLMacro?\def\CheckboardHook;{% - \psframe[linestyle=none,fillstyle=hlines](0,6)(1,7)} - % /HLComment?White pieces changed by the black move; - \Checkboard(3,1)={B}\Checkboard(4,1)={B} - \Checkboard(2,2)={B}\Checkboard(3,2)={B} - \vspace{1cm} - \ShowCheckboard -\end{SideBySideExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - - Note also that, if \TeX{} is obviously not well suited to implement a -program to \emph{really} play at a game like reversi or chess, nevertheless -it can be used to solve internally some non trivial algorithmic problems, -where the usage of arrays help a lot. For such example (on the coloration of -the Truchet's tiling), see \cite{EG98}. - -\subsection{Advanced examples} - - This section will show slightly more difficult to really complex examples, -and is mainly for \emph{advanced users} or for people who want to be able to -program complex tasks themselves. - -\subsubsection{Example with recursion usage} - -\begin{CenterExample} - \makeatletter - - % /HLComment?The recursion macro used (from David Carlisle); - /HLMacro?\def\Recursion;#1{% - #1\relax - \expandafter\@firstoftwo - \else - \expandafter\@secondoftwo - \fi} - - \newcount\IndexRecursion - \IndexRecursion=\z@ - - /HLMacro?\def\PiFrac;#1{{% - \Recursion - {\ifnum#1>\@ne\relax} - {\@tempcnta=#1 - \advance\@tempcnta\m@ne - \advance\IndexRecursion\@ne - \PiValues(\IndexRecursion) - +\frac{\strut\displaystyle 1}{\strut\displaystyle\PiFrac{\@tempcnta}}} - {\advance\IndexRecursion\@ne - \PiValues(\IndexRecursion)}}} - - \makeatother - - \newarray\PiValues - \readarray{/HLReverse?PiValues;}{3&7&15&1&292&1&1&1&2&1&3&1&14} - - \(\pi\approx\PiFrac{/HLReverse?4;}\approx\PiFrac{/HLReverse?13;}\) - - \textbf{\(\pi\) as a continued fraction} -\end{CenterExample} - -\subsubsection{Structured dynamic diagrams on a grid} - - A very common case is when we must use some strutured data which are to be -drawn on a kind of abstract grid. - -\ifpstricks % If PSTricks is available - To draw a diagram like this one (such example illustrate the exchanges of -data between processors when using applications on multiprocessors computers -in parallel programming): - -\vspace{2mm} -\begin{SideBySideExample}[xrightmargin=5.8cm] - \psset{linestyle=none,fillstyle=solid,subgriddiv=0,gridlabels=0} - \begin{pspicture}(-1,0)(4,4) - % /HLComment?Line 0; - \psframe[fillcolor=Khaki](0,3.1)(1,3.9) - \psframe[fillcolor=LemonChiffon](1,3.1)(4,3.9) - \rput(0,3.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,3.5){P0} - \rput(0.5,3.5){A0} - % /HLComment?Line 1; - \psframe[fillcolor=Khaki](0,2.1)(2,2.9) - \psframe[fillcolor=LemonChiffon](2,2.1)(4,2.9) - \rput(0,2.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,2.5){P1} - \rput(0.5,2.5){A0}\rput(1.5,2.5){A1} - % /HLComment?Line 2; - \psframe[fillcolor=Khaki](0,1.1)(3,1.9) - \psframe[fillcolor=LemonChiffon](3,1.1)(4,1.9) - \rput(0,1.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,1.5){P2} - \rput(0.5,1.5){A0}\rput(1.5,1.5){A1}\rput(2.5,1.5){A2} - % /HLComment?Line 3; - \psframe[fillcolor=Khaki](0,0.1)(4,0.9) - \rput(0,0.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,0.5){P3} - \rput(0.5,0.5){A0}\rput(1.5,0.5){A1} - \rput(2.5,0.5){A2}\rput(3.5,0.5){A3} - \end{pspicture} -\end{SideBySideExample} - -\vspace{2mm} -\noindent is easy but rather painful, as we must manage a lot of coordinates. -Nevertheless, even if we introduce a little more abstraction level using some -minor programming with a loop structure: -\vspace{2mm} - - -\begin{SideBySideExample}[xrightmargin=5.8cm] - \psset{linestyle=none,fillstyle=solid,subgriddiv=0,gridlabels=0} - \begin{pspicture}(-1,0)(4,4) - \multido{\iLoop=1+1,\iRow=0+1,\iRowPos=3+-1}{4}{% - \psframe[fillcolor=Khaki](0,\iRowPos.1)(\iLoop,\iRowPos.9) - \psframe[fillcolor=LemonChiffon] - (\iLoop,\iRowPos.1)(4,\iRowPos.9) - \rput(0,\iRowPos.1){\psgrid[yunit=0.8](4,1)} - \rput(-0.5,\iRowPos.5){P\iRow} - \multido{\iColumn=0+1,\iLabel=1+1}{\iLoop}{% - \rput(\iColumn.5,\iRowPos.5){A\iColumn}}} - \end{pspicture} -\end{SideBySideExample} - -\vspace{2mm} -\noindent we succeed to heavily reduce the number of lines of the code in this -specific case, but we gain nothing in genericity. If we have several such -diagrams to draw, with each that must be done differently according to the -empty and full cells of the array, we must proceed in a completely different -way, defining a \emph{generic object} which can obtain the different values of -a data structure previously filled. For such tasks, the \ArrayJobPackage{} -package allow to build very efficient and powerful tools. - -\begin{Verbatim}[commandchars=/?;] - % /HLComment?The grid; - /HLMacro?\def\ArrayGrid;#1#2#3{{% - % /HLComment?#1=array of data, #2=number of rows, #3=number of columns; - \psset{dimen=middle,xunit=0.8} - \dataheight=#3 - \pspicture(-1,-#2)(#3,0) - \multido{\iRow=1+1,\iRowMinusOne=0+1}{#2}{% - \rput(-1,-\iRow){\LineGrid{#1}{\iRow}{\iRowMinusOne}{#3}}} - \endpspicture}} - - % /HLComment?One line of the grid; - /HLMacro?\def\LineGrid;#1#2#3#4{% - \rput(0.5,0.4){\AttributeLabel{P#3}} - \multido{\iColumn=1+1}{#4}{% - \expandafter\csname check#1\endcsname(#2,\iColumn)% - \rput(\iColumn,0){% - \ifemptydata - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \ifx\cachedata\space - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \def\ColorBackground{\ColorBackgroundFull}% - \fi - \fi - \psframe[fillstyle=solid,fillcolor=\ColorBackground](1,0.8) - \rput(0.5,0.4){\AttributeElement{\cachedata}}}}} -\end{Verbatim} - -% The grid -\def\ArrayGrid#1#2#3{{% -% #1=array of data, #2=number of rows, #3=number of columns -\psset{dimen=middle,xunit=0.8} -\dataheight=#3 -\pspicture(-1,-#2)(#3,0) -\multido{\iRow=1+1,\iRowMinusOne=0+1}{#2}{% - \rput(-1,-\iRow){\LineGrid{#1}{\iRow}{\iRowMinusOne}{#3}}} -\endpspicture}} - -% One line of the grid -\def\LineGrid#1#2#3#4{% -\rput(0.3,0.4){\AttributeLabel{P#3}} -\multido{\iColumn=1+1}{#4}{% - \expandafter\csname check#1\endcsname(#2,\iColumn)% - \rput(\iColumn,0){% - \ifemptydata - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \ifx\cachedata\space - \def\ColorBackground{\ColorBackgroundEmpty}% - \else - \def\ColorBackground{\ColorBackgroundFull}% - \fi - \fi - \psframe[fillstyle=solid,fillcolor=\ColorBackground](1,0.8) - \rput(0.5,0.4){\AttributeElement{\cachedata}}}}} - -\begin{SideBySideExample}[xrightmargin=6cm] - % /HLComment?Default attributes; - \def\ColorBackgroundEmpty{LemonChiffon} - \def\ColorBackgroundFull{Khaki} - \def\AttributeElement#1{\textcolor{red}{#1}} - \def\AttributeLabel#1{\bf #1} - - % /HLComment?Example 1; - \newarray\ArrayA - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A0& & & &% - A0&A1& & &% - A0&A1&A2& &% - A0&A1&A2&A3} - - \ArrayGrid{ArrayA}{4}{4} -\end{SideBySideExample} - -\newarray\ArrayA - -% Default attributes -\def\ColorBackgroundEmpty{LemonChiffon} -\def\ColorBackgroundFull{Khaki} -\def\AttributeElement#1{\textcolor{red}{#1}} -\def\AttributeLabel#1{\bf #1} - -\begin{CenterExample}[baselinestretch=0.9] - % /HLComment?Example 2; - \newarray\ArrayB - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A& & & &% - & & & &% - & & & &% - & & & } - \readarray{/HLReverse?ArrayB;}{% - A& & & &% - A& & & &% - A& & & &% - A& & & } - - \ArrayGrid{ArrayA}{4}{4}\hfill\ArrayGrid{ArrayB}{4}{4} -\end{CenterExample} - -\newarray\ArrayB - -\begin{CenterExample}[baselinestretch=0.9] - % /HLComment?Example 3; - \newarray\ArrayC - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A0& & &% - A1& & &% - A2& & } - \readarray{/HLReverse?ArrayB;}{% - A0&A1&A2&% - A0&A1&A2&% - A0&A1&A2} - \readarray{/HLReverse?ArrayC;}{% - A0& & &% - &A1& &% - & &A2} - - % /HLComment?Attributes; - \def\ColorBackgroundEmpty{green} - \def\ColorBackgroundFull{red} - \def\AttributeElement#1{\footnotesize\textcolor{white}{#1}} - \def\AttributeLabel#1{\small\bf #1} - - \psset{unit=0.7} - \ArrayGrid{ArrayA}{3}{3}\hfill\ArrayGrid{ArrayB}{3}{3}\hfill\ArrayGrid{ArrayC}{3}{3} -\end{CenterExample} - -\begin{CenterExample}[baselinestretch=0.9] - % /HLComment?Example 4; - - % /HLComment?Data; - \readarray{/HLReverse?ArrayA;}{% - A0&A1&A2&A3&% - B0&B1&B2&B3&% - C0&C1&C2&C3&% - D0&D1&D2&D3} - \readarray{/HLReverse?ArrayB;}{% - A0&B0&C0&D0&% - A1&B1&C1&D1&% - A2&B2&C2&D2&% - A3&B3&C3&D3} - - % /HLComment?Attributes; - \def\AttributeElement#1{\textcolor{red}{#1}} - \def\AttributeLabel#1{\Large\it #1} - - \ArrayGrid{ArrayA}{4}{4}\hfill\ArrayGrid{ArrayB}{4}{4} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\vspace{5mm} -\subsubsection{Another example of a structured dynamic diagram on a grid} - - The preceding technique is in fact relevant for a lot of problems. Here we -give another example about the drawing of linked lists (but do not fail to -note that these ones have here no internal existence). - -\ifpstricks % If PSTricks is available -\begin{CenterExample} - \makeatletter - - \newpsstyle{LinkedListsArrowStyle}{linecolor=red,arrowscale=2} % /HLComment?Default arrow style; - - /HLMacro?\def\LinkedListsDraw;{\@ifnextchar[\LinkedListsDraw@i{\LinkedListsDraw@i[]}} - - /HLMacro?\def\LinkedListsDraw@i;[#1]#2#3{{% - \setkeys{psset}{#1} - \dataheight=#3 - % - \pst@cnta=#3 - \multiply\pst@cnta\tw@ - \advance\pst@cnta\tw@ - \pspicture(0,-#2)(\pst@cnta,0) - \multido{\iRow=1+1}{#2}{% - \rput(0,-\iRow){% - \psframe(1,1) - \psline[dimen=middle,style=LinkedListsArrowStyle]{->}(0.5,0.5)(2,0.5)} - \multido{\iColumn=1+1}{#3}{% - \checkLinkedListsTable(\iRow,\iColumn)% - \ifemptydata - \else - \pst@cnta=\iColumn - \advance\pst@cnta\@ne - \pst@cntb=\@ne - \checkLinkedListsTable(\iRow,\pst@cnta)% - \ifemptydata % /HLComment?We test if it is empty; - \else - \ifnum\multidocount=#3 % /HLComment?We test if it is the last one; - \else - \pst@cntb=\z@ - \fi - \fi - % - \pst@cnta=\iColumn - \multiply\pst@cnta\tw@ - \rput(\the\pst@cnta,-\iRow){% - \LinkedListsDraw@ii{\LinkedListsTable(\iRow,\iColumn)}{\the\pst@cntb}} - \fi}} - \endpspicture}}%} - - /HLMacro?\def\LinkedListsDraw@ii;#1#2{{% - \rput(0,0.1){% - \psset{unit=0.8} - \psgrid[subgriddiv=0,gridlabels=0](2,1) % /HLComment?Element; - \rput(0.5,0.5){#1} % /HLComment?Label for this element; - \ifnum#2=\@ne - \psline(1,0)(2,1) % /HLComment?Mark of the end of the list; - \else - \psline[style=LinkedListsArrowStyle]{->}(1.5,0.5)(2.5,0.5) % /HLComment?Link to the next element; - \fi}}} - - \makeatother - - \newarray\LinkedListsTable - \readarray{/HLReverse?LinkedListsTable;}{% - 11&12&13&14&% - 21&&&&% - 31&32&33&&} - - \LinkedListsDraw{3}{4} - - \vspace{1cm} - \newpsstyle{LinkedListsArrowStyle}{linecolor=green,doubleline=true} - - \readarray{/HLReverse?LinkedListsTable;}{% - a&&&&&% - A&B&C&D&E&% - 0&1&2&3&4&% - +&$\times$&&&&} - - \LinkedListsDraw{4}{5} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\subsubsection{Management of heaps and linked lists} - - Here we will demonstrate a really more complex usage, but very useful. -In fact, if the \ArrayJobPackage{} package primarily allow to manage only -arrays, it allow a lot more with some efforts. Above it, we can implement the -common internal data structures frequently used in programming, like heaps, -simple or double linked lists, trees, associative arrays, etc. Here we will -show how to define macros to build and manage heaps and simple linked lists. - -\ifpstricks % If PSTricks is available -\vspace{1cm} % Poor hack to force a page break... -\begin{CenterExample}[baselinestretch=0.98] - \makeatletter - - /HLMacro?\def\PstDebug;{\z@} % /HLComment?For debugging, set \def\PstDebug{1}; - - % /HLComment?Code for heaps management; - % /HLComment?-------------------------; - - /HLMacro?\def\HeapMaxDepth;{100} % /HLComment?No more than 100 elements in the heap; - - \newarray\Heap - - % /HLComment?Add an element at top of the heap; - /HLMacro?\def\HeapPush;#1{% - \multido{\iElem=1+1}{\HeapMaxDepth}{% - \checkHeap(\iElem)% - \ifemptydata - \ifnum\PstDebug=\@ne\typeout{Push Heap(\iElem)=#1}\fi% /HLComment?Debug; - \Heap(\iElem)={#1}% - \multidostop - \fi}} - - % /HLComment?Get (in the \cachedata macro) and delete the element at top of the heap; - /HLMacro?\def\HeapPop;{% - \Multido{\iElem=\HeapMaxDepth+-1}{\HeapMaxDepth}{% - \checkHeap(\iElem)% - \ifemptydata - \else - \ifnum\PstDebug=\@ne\typeout{Delete Heap(\iElem)=\cachedata}\fi% /HLComment?Debug; - \Heap(\iElem)={}% - \multidostop - \fi}} - - % /HLComment?Print the current state of the heap; - /HLMacro?\def\HeapPrint;{% - \checkHeap(\@ne)% - \ifemptydata - \typeout{The heap is empty!}% /HLComment?Empty heap; - \else - \multido{\iElem=\HeapMaxDepth+-1}{\HeapMaxDepth}{% - \checkHeap(\iElem)% - \ifemptydata - \else - \typeout{Heap(\iElem)=\cachedata}% - \fi} - \fi - \typeout{}} - - % /HLComment?Draw the current state of the heap; - /HLMacro?\def\HeapDraw;{% - % /HLComment?To compute the size of the picture; - \Multido{\iSize=0+1}{\HeapMaxDepth}{% - \checkHeap(\the\multidocount)% - \ifemptydata - \multidostop - \fi} - % - \ifnum\iSize=\z@ - % /HLComment?Empty heap; - \typeout{The heap is empty!^^J}% - \else - \pspicture(1,\iSize) - \psgrid[subgriddiv=0,gridlabels=0](1,\iSize) - \multido{\iPos=0+1}{\HeapMaxDepth}{% - \checkHeap(\the\multidocount)% - \ifemptydata - \multidostop - \else - \rput(0.5,\iPos.5){\cachedata} - \fi} - \endpspicture% - \fi} - - \makeatother - - \psset{unit=1.5}\footnotesize - - \HeapPush{Germany}\HeapPrint\HeapDraw - \hfill - \HeapPush{France}\HeapPrint\HeapDraw - \hfill - \HeapPush{Italy}\HeapPrint\HeapDraw - \hfill - \HeapPush{Spain}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw - \hfill - \HeapPop\typeout{Popped element: `\cachedata'}\HeapPrint\HeapDraw -\end{CenterExample} - -\begin{Example}[baselinestretch=0.95] - \makeatletter - - /HLMacro?\def\PstDebug;{\z@}% /HLComment?For debugging, set \def\PstDebug{1}; - - % /HLComment?Code for linked lists management; - % /HLComment?--------------------------------; - - /HLMacro?\def\LinkedListMaxDepth;{100}% /HLComment?No more than 100 elements in the list; - - \newarray\LinkedList - - \dataheight=2% /HLComment?Two cells by element: the content and the pointer; - - % /HLComment?Add an element at the end of the list; - % /HLComment?In fact, we define it here as a simple heap, but the difference is that; - % /HLComment?we will be able to get and to delete any element in it; - /HLMacro?\def\LinkedListAdd;#1{% - \edef\@tempa{\@ne}% /HLComment?Pointer initialization; - \multido{\iElem=2+1}{\LinkedListMaxDepth}{% - \checkLinkedList(\@tempa,2)% /HLComment?We got the content of this element; - \ifemptydata - % /HLComment?No pointed element, so we will insert the new one here; - \LinkedList(\iElem,1)={#1}% - % /HLComment?We update the pointer for the last preceding element; - \expandarrayelementtrue% /HLComment?We must evaluate the content of the counter; - \LinkedList(\@tempa,2)={\iElem}% - \expandarrayelementfalse - \ifnum\PstDebug=\@ne - \typeout{Add LinkedList(\@tempa)->\iElem}% /HLComment?Debug; - \typeout{\space\space\space\space LinkedList(\iElem)=#1}% /HLComment?Debug; - \fi - \multidostop - \else - \edef\@tempa{\cachedata}% - \fi}} - - % /HLComment?Get (in the \cachedata macro) the next element in the list; - /HLMacro?\def\LinkedListGetNext;#1{% - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \edef\@tempa{\@ne}% - \ifx\cachedata\empty - \else - \edef\@tempc{#1}% - \Multido{}{\LinkedListMaxDepth}{% - \edef\@tempb{\@tempa}% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \ifx\cachedata\@tempc - % /HLComment?This is the element for which we want the next one: we got it pointer; - % /HLComment?to the next element in the list, then the content of it; - \checkLinkedList(\@tempa,2)% - \ifemptydata - \typeout{Element `#1' has no successor!^^J}% - \else - \checkLinkedList(\cachedata,1)% - \fi - \multidostop - \else - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - % /HLComment?We have reach the end of the list without finding the element; - \typeout{Element `#1' not found!^^J}% - \multidostop% /HLComment?No pointed element: end of the list; - \fi - \fi} - \fi} - - % /HLComment?Delete an element in the list (the code is very close to \LinkedListGetNext); - /HLMacro?\def\LinkedListDelete;#1{% - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \edef\@tempa{\@ne}% - \ifx\cachedata\empty - \else - \edef\@tempc{#1}% - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempb{\@tempa}% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \ifx\cachedata\@tempc - % /HLComment?This is the element to delete: we will update the pointer of; - % /HLComment?the preceding element to the value of the pointer of the deleted one; - \checkLinkedList(\@tempa,2)% - \expandarrayelementtrue - \LinkedList(\@tempb,2)={\cachedata}% - \expandarrayelementfalse - \ifnum\PstDebug=\@ne - \typeout{Delete LinkedList(\@tempa)=#1}% /HLComment?Debug; - \typeout{\space\space\space\space\space\space\space % - LinkedList(\@tempb)->\cachedata}% /HLComment?Debug; - \fi - \multidostop - \else - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - % /HLComment?We have reach the end of the list without finding the element; - \typeout{Element `#1' not found and so not deleted!^^J}% - \multidostop% /HLComment?No pointed element: end of the list; - \fi - \fi} - \fi} - - % /HLComment?Print the current state of the list; - /HLMacro?\def\LinkedListPrint;{% - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \ifx\cachedata\empty - % /HLComment?Empty list; - \typeout{The list is empty!}% - \else - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \typeout{LinkedList=\cachedata}% - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - \multidostop% /HLComment?No pointed element: end of the list; - \fi} - \fi - \typeout{}} - - % /HLComment?Draw the current state of the list; - /HLMacro?\def\LinkedListDraw;{{% - \psset{subgriddiv=0,gridlabels=0} - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \ifx\cachedata\empty - % /HLComment?Empty list; - \typeout{The list is empty!^^J}% - \else - % /HLComment?To compute the size of the picture; - \Multido{\iSize=3+3}{\LinkedListMaxDepth}{% - \checkLinkedList(\cachedata,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - \multidostop - \fi} - % - \checkLinkedList(1,2)% /HLComment?We got the pointer for the first element; - \pspicture(\iSize,1.5) - \multido{\iPos=0+3}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% /HLComment?We got the pointed element; - \rput(\iPos,0){% - \psgrid(2,1) - \rput(0.5,0.5){\cachedata} - \ifnum\iPos=\z@ - \else - \rput(-1.5,0.5){\psline[linecolor=red,arrowscale=2]{->}(1.5,0)} - \fi} - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer to the next element; - \ifemptydata - \rput(\iPos,0){\psline[linecolor=red](1,0)(2,1)} % /HLComment?End of the list; - \multidostop% /HLComment?No pointed element: end of the list; - \fi} - \endpspicture% - \fi}} - - \makeatother - - \psset{unit=1.5} - - \LinkedListPrint\LinkedListDraw - - \LinkedListAdd{Germany}\LinkedListPrint\LinkedListDraw - - \LinkedListAdd{France}\LinkedListPrint\LinkedListDraw - - \LinkedListAdd{Italy}\LinkedListPrint\LinkedListDraw - - \LinkedListAdd{Spain}\LinkedListPrint\LinkedListDraw - - \LinkedListGetNext{France}\typeout{Next element after `France' is: `\cachedata'}% - \LinkedListGetNext{Germany}\typeout{Next element after `Germany is: `\cachedata'}% - \LinkedListGetNext{Spain} - \LinkedListGetNext{Unknown} - - \LinkedListDelete{Unknown} - - \LinkedListDelete{France}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{Germany}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{Spain}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{Italy}\LinkedListPrint\LinkedListDraw -\end{Example} - -\makeatletter - -\def\PstDebug{\z@}% For debugging, set \def\PstDebug{1} - -\def\LinkedListMaxDepth{100}% No more than 100 elements in the heap - -\newarray\LinkedList - -\dataheight=2% Two cells by element: the content and the pointer - -% Delete an element in the list -\def\LinkedListDelete#1{% -\checkLinkedList(1,2)% We got the pointer for the first element -\edef\@tempa{\@ne}% -\ifx\cachedata\empty -\else - \edef\@tempc{#1}% - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempb{\@tempa}% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% We got the pointed element - \ifx\cachedata\@tempc - % This is the element to delete: we will update the pointer of - % the preceding element to the value of the pointer of the deleted one - \checkLinkedList(\@tempa,2)% - \expandarrayelementtrue - \LinkedList(\@tempb,2)={\cachedata}% - \expandarrayelementfalse - \ifnum\PstDebug=\@ne - \typeout{Delete LinkedList(\@tempa)=#1}%Debug - \typeout{\space\space\space\space\space\space\space % - LinkedList(\@tempb)->\cachedata}%Debug - \fi - \multidostop - \else - \checkLinkedList(\@tempa,2)% We got the pointer to the next element - \ifemptydata - % We have reach the end of the list without finding the element - \typeout{Element `#1' not found and so not deleted!^^J}% - \multidostop% No pointed element: end of the list - \fi - \fi} -\fi} - -% Print the current state of the list -\def\LinkedListPrint{% -\checkLinkedList(1,2)% We got the pointer for the first element -\ifx\cachedata\empty - % Empty list - \typeout{The list is empty!}% -\else - \multido{}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% We got the pointed element - \typeout{LinkedList=\cachedata}% - \checkLinkedList(\@tempa,2)% We got the pointer to the next element - \ifemptydata - \multidostop% No pointed element: end of the list - \fi} -\fi -\typeout{}} - -% Draw the current state of the list -\def\LinkedListDraw{{% -\psset{subgriddiv=0,gridlabels=0} -\checkLinkedList(1,2)% We got the pointer for the first element -\ifx\cachedata\empty - % Empty list - \typeout{The list is empty!^^J}% -\else - % To compute the size of the picture - \Multido{\iSize=3+3}{\LinkedListMaxDepth}{% - \checkLinkedList(\cachedata,2)% We got the pointer to the next element - \ifemptydata - \multidostop - \fi} - % - \checkLinkedList(1,2)% We got the pointer for the first element - \pspicture(\iSize,1.5) - \multido{\iPos=0+3}{\LinkedListMaxDepth}{% - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% We got the pointed element - \rput(\iPos,0){% - \psgrid(2,1) - \rput(0.5,0.5){\cachedata} - \ifnum\iPos=\z@ - \else - \rput(-1.5,0.5){\psline[linecolor=red,arrowscale=2]{->}(1.5,0)} - \fi} - \checkLinkedList(\@tempa,2)% We got the pointer to the next element - \ifemptydata - \rput(\iPos,0){\psline[linecolor=red](1,0)(2,1)} % End of the list - \multidostop% No pointed element: end of the list - \fi} - \endpspicture% -\fi}} - -\makeatother - -% We clear the linked list -\multido{\iElem=1+1}{\LinkedListMaxDepth}{% - \checkLinkedList(\iElem,1)% - \ifemptydata - \else - \LinkedList(\iElem,1)={}% - \LinkedList(\iElem,2)={}% - \fi} - -\vspace{2mm} - We can write an extended version of the inclusion of an element, where we do -not still store each element at the end of the list, but insert it at a -special position. For instance, we can decide to use the list to sort the -elements, inserting a new one at it sorted position. In the next example, we -will manage integer numbers in this way (of course, we can do the same thing -with arbitrary strings, but it would be more difficult to program in \TeX{}, -mainly if we want to be able to use accentuated letters). - -\vspace{2mm} -\begin{Example} - \makeatletter - - % /HLComment?Add an element at the end of the list, linked in it ordered place; - % /HLComment?(this version work only with contents as numbers); - /HLMacro?\def\LinkedListSortedAdd;#1{% - % /HLComment?Initializations; - \edef\@tempa{\@ne}% - \edef\@tempb{\@ne}% - \edef\@tempc{\z@}% - % - \multido{\iElem=2+1}{\LinkedListMaxDepth}{% - \checkLinkedList(\@tempa,2)% /HLComment?We got the pointer of this element; - \ifemptydata - % /HLComment?No pointed element, so we will insert the new one here; - \LinkedList(\iElem,1)={#1}% - % /HLComment?We update the pointer for the last element; - \expandarrayelementtrue - \LinkedList(\@tempb,2)={\iElem}% - \ifnum\PstDebug=\@ne - \typeout{Add LinkedList(\@tempb)->\iElem}% /HLComment?Debug; - \typeout{\space\space\space\space LinkedList(\iElem)=#1}% /HLComment?Debug; - \fi - % /HLComment?We update the pointer of the new element to the position; - % /HLComment?of the next greater one, if it exist; - \ifnum\@tempc=\z@ - \else - \LinkedList(\iElem,2)={\@tempc}% - \ifnum\PstDebug=\@ne - \typeout{Update LinkedList(\iElem)->\@tempc}% /HLComment?Debug; - \fi - \fi - \expandarrayelementfalse - \multidostop - \else - \edef\@tempa{\cachedata}% - \checkLinkedList(\cachedata,1)% - \ifnum#1<\cachedata - \edef\@tempc{\@tempa}% /HLComment?New element less than this one; - \else - \edef\@tempb{\@tempa}% /HLComment?New element greater or equal than this one; - \fi - \fi}} - - \makeatother - - \LinkedListPrint - - \LinkedListSortedAdd{732}\LinkedListPrint\LinkedListDraw - - \LinkedListSortedAdd{487}\LinkedListPrint\LinkedListDraw - - \LinkedListSortedAdd{718}\LinkedListPrint\LinkedListDraw - - \LinkedListSortedAdd{962}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{487}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{732}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{500} - - \LinkedListDelete{962}\LinkedListPrint\LinkedListDraw - - \LinkedListDelete{718}\LinkedListPrint\LinkedListDraw -\end{Example} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\subsubsection{Associative arrays} - - To finish, we will give a complete solution to a classical problem: to count -the number of occurrences of the various letters in a sentence. For this, we -will first build some macros to deal with \emph{associative} arrays, as they -have been popularized by scripting languages like \texttt{AWK} and -\texttt{Perl}. - -\begin{Example} - \makeatletter - - % /HLComment?Internally, we use two "standard" arrays to define one associative array; - \newarray\AssociativeArray@Names - \newarray\AssociativeArray@Values - - \newcount\AssociativeArrayNbValues - \AssociativeArrayNbValues=\z@ - - \newif\ifAssociativeArray@ElementFound - - % /HLComment?To store one element; - /HLMacro?\def\AssociativeArray;(#1)=#2{% - \expandarrayelementtrue - \AssociativeArray@ElementFoundfalse - \edef\@tempa{#1}% - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % /HLComment?This element already exist: we replace it current value; - % /HLComment?\checkAssociativeArray@Values(\iValue)% Debug; - % /HLComment?\typeout{In #1, replace `\cachedata'\space by `#2'}% Debug; - \AssociativeArray@Values(\iValue)={#2}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} - \ifAssociativeArray@ElementFound - \else - % /HLComment?New element; - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={#1}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={#2}% - \fi} - - % /HLComment?To get one element; - /HLMacro?\def\checkAssociativeArray;(#1){% - \edef\@tempa{#1}% - \edef\@tempb{999999}% - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % /HLComment?We have found it by name; - \edef\@tempb{\iValue}% - \multidostop - \fi} - % /HLComment?We have now to get it value; - \checkAssociativeArray@Values(\@tempb)} - - % /HLComment?Simple macro to print all the associative array; - /HLMacro?\def\printAssociativeArray;{% - \multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \iValue: \BS\texttt{FirstNames(\cachedata)}=`\AssociativeArray@Values(\iValue)'\space}} - - \makeatother - - \let\FirstNames\AssociativeArray - \let\checkFirstNames\checkAssociativeArray - \let\printFirstNames\printAssociativeArray - - \FirstNames(Crawford)={Joan} - \FirstNames(Tierney)={Gene} - \FirstNames(Lake)={Veronika} - - \printFirstNames - - \checkFirstNames(Lake) - \verb+\FirstNames(Lake)+=`\cachedata' - - \checkFirstNames(Monroe) - \ifemptydata - \verb+\FirstNames(Monroe) undefined!+ - \else - \verb+\FirstNames(Monroe)+=`\cachedata' - \fi -\end{Example} - -\makeatletter - -% Internally, we use two "standard" arrays to define one associative array -\newarray\AssociativeArray@Names -\newarray\AssociativeArray@Values - -\newcount\AssociativeArrayNbValues -\AssociativeArrayNbValues=\z@ - -\newif\ifAssociativeArray@ElementFound - -% To store one element -\def\AssociativeArray(#1)=#2{% -\expandarrayelementtrue -\AssociativeArray@ElementFoundfalse -\edef\@tempa{#1}% -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % This element already exist: we replace it current value - % \checkAssociativeArray@Values(\iValue)% debug - % \typeout{In #1, replace `\cachedata'\space by `#2'}% Debug - \AssociativeArray@Values(\iValue)={#2}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} -\ifAssociativeArray@ElementFound -\else - % New element - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={#1}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={#2}% -\fi} - -% To get one element -\def\checkAssociativeArray(#1){% -\edef\@tempa{#1}% -\edef\@tempb{999999}% -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % We have found it by name - \edef\@tempb{\iValue}% - \multidostop - \fi} -% We have now to get it value -\checkAssociativeArray@Values(\@tempb)} - -% Simple macro to print all the associative array -\def\printAssociativeArray{% -\multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \iValue: \BS\texttt{FirstNames(\cachedata)}=`\AssociativeArray@Values(\iValue)'}} - -\makeatother - -\vspace{2mm} - Now, we can define the macros to read a sentence, to cut it letter by letter, -to count the occurrences of each of them, and finally to draw a summary plot of -the results. - -\makeatletter % Problem with the \ifpstricks conditional if not set... - -\ifpstricks % If PSTricks is available -\begin{CenterExample} - \makeatletter - - % /HLComment?A \PerChar style macro adapted from Juergen Schlegelmilch; - % /HLComment?(<schlegel@Informatik.Uni-Rostock.de> - posted on c.t.t. January 27, 1998); - /HLMacro?\def\PerChar;#1#2{\DoPerChar#1#2\@nil} - - /HLMacro?\def\DoPerChar;#1#2#3\@nil{% - #1#2% - \edef\@tempa{#3}% - \ifx\@tempa\empty - \else - \DoPerChar#1#3\@nil - \fi} - - % /HLComment?The action to do for each character: we increase the counter; - % /HLComment?for this character by one; - /HLMacro?\def\ActionPerChar;#1{% /HLComment?#1=character; - \checkAssociativeArray(#1)% - \ifemptydata - \@tempcnta=\@ne - \else - \@tempcnta=\cachedata - \advance\@tempcnta\@ne - \fi - \AssociativeArray(#1)={\the\@tempcnta}} - - % /HLComment?To store in an associative array the number of occurrences by characters; - % /HLComment?(spaces are not counted); - /HLMacro?\def\StatSentence;#1{% /HLComment?#1=sentence; - \AssociativeArrayNbValues=\z@ - \PerChar{\ActionPerChar}{#1}} - - % /HLComment?To draw a plot of the number of occurrences of the characters of a sentence; - /HLMacro?\def\DrawOccurrences;#1{% /HLComment?#1=sentence; - \StatSentence{#1} - % - \pst@cnta=\AssociativeArrayNbValues - \advance\pst@cnta\@ne - % - % /HLComment?To know the maximum of the numbers; - \pst@cntb=\z@ - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Values(\iValue)% - \ifnum\cachedata>\pst@cntb - \pst@cntb=\cachedata - \fi} - \advance\pst@cntb\@ne - % - % /HLComment?The drawing itself; - \pspicture(-0.5,-0.5)(\pst@cnta,\pst@cntb) - \psaxes[axesstyle=frame,labels=y](\pst@cnta,\pst@cntb) - \multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \Draw@OneOccurrence{\iValue}} - \endpspicture} - - % /HLComment?To draw the value for one occurrence; - /HLMacro?\def\Draw@OneOccurrence;#1{% /HLComment?#1=Letter; - \checkAssociativeArray@Values(#1)% - \psdot(#1,\cachedata) - \rput[B](\iValue,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \let\Names\AssociativeArray - \let\checkNames\checkAssociativeArray - - \psset{dotstyle=o,dotsize=0.4} - - \DrawOccurrences{We are Wednesday} -\end{CenterExample} - -\makeatletter - -%% A \PerChar style macro adapted from Juergen Schlegelmilch -%% (<schlegel@Informatik.Uni-Rostock.de> - posted on c.t.t. Jan. 27, 1998) -\def\PerChar#1#2{\DoPerChar#1#2\@nil} - -\def\DoPerChar#1#2#3\@nil{% -#1#2% -\edef\@tempa{#3}% -\ifx\@tempa\empty -\else - \DoPerChar#1#3\@nil -\fi} - -% The action to do for each character: we increase the counter -% for this character by one -\def\ActionPerChar#1{% #1=character -\checkAssociativeArray(#1)% -\ifemptydata - \@tempcnta=\@ne -\else - \@tempcnta=\cachedata - \advance\@tempcnta\@ne -\fi -\AssociativeArray(#1)={\the\@tempcnta}} - -% To store in an associative array the number of occurrences by characters -% (spaces are not counted) -\def\StatSentence#1{% #1=sentence -\AssociativeArrayNbValues=\z@ -\PerChar{\ActionPerChar}{#1}} - -% To draw a plot of the number of occurrences of the characters of a sentence -\def\DrawOccurrences#1{% -\StatSentence{#1} -% -\pst@cnta=\AssociativeArrayNbValues -\advance\pst@cnta\@ne -% -% To know the maximum of the numbers -\pst@cntb=\z@ -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Values(\iValue)% - \ifnum\cachedata>\pst@cntb - \pst@cntb=\cachedata - \fi} -\advance\pst@cntb\@ne -% -% The drawing itself -\pspicture(-0.5,-0.5)(\pst@cnta,\pst@cntb) - \psaxes[axesstyle=frame,labels=y](\pst@cnta,\pst@cntb) - \multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \Draw@OneOccurrence{\iValue}} -\endpspicture} - -% To draw the value for one occurrence -\def\Draw@OneOccurrence#1{% -\checkAssociativeArray@Values(#1)% -\psdot(#1,\cachedata) -\rput[B](\iValue,-0.5){\AssociativeArray@Names(#1)}} - -\let\Names\AssociativeArray -\let\checkNames\checkAssociativeArray - -\psset{dotstyle=o,dotsize=0.4} - -\makeatother - -\vspace{8mm} % Poor hack to force a page break... - We will now write another version, using another array to store indexes, -to allow us to sort the letters found in the sentence read. - -\begin{CenterExample} - \makeatletter - - % /HLComment?To get in #2 the ASCII code of the #1 character; - /HLMacro?\def\Character@AsciiCode;#1#2{\chardef#2=`#1\relax} - - % /HLComment?A new "standard" array to store the sorted indexes; - \newarray\AssociativeArray@Indexes - - % /HLComment?A simple macro to print the array of indexes (for debugging); - /HLMacro?\def\PrintIndexes;{% - \multido{\iIndexes=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Indexes(\iIndexes)% - \BS\texttt{indexes(\iIndexes)}=`\cachedata'\space}} - - % /HLComment?We redefine the macro to store an element in the associative array,; - % /HLComment?to allow to sort it elements, using an additional array of indexes; - /HLMacro?\def\AssociativeArray;(#1)=#2{% - \expandarrayelementtrue - \AssociativeArray@ElementFoundfalse - \edef\@tempa{#1}% - \edef\@tempb{#2}% - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % /HLComment?This element already exist: we replace it current value; - % /HLComment?\checkAssociativeArray@Values(\iValue)% Debug; - % /HLComment?\typeout{In #1, replace `\cachedata'\space by `#2'}% Debug; - \AssociativeArray@Values(\iValue)={\@tempb}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} - \ifAssociativeArray@ElementFound - \else - % /HLComment?New element: we must insert it at it sorted position; - \@tempcnta=\@ne - \expandafter\Character@AsciiCode\@tempa\@tempx - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \expandafter\Character@AsciiCode\cachedata\@tempy - \ifnum\@tempx<\@tempy - % /HLComment?The new element must be before this one: we will exchange their values; - \checkAssociativeArray@Indexes(\iValue)% - \@tempcntb=\cachedata - \advance\@tempcntb\@ne - \AssociativeArray@Indexes(\iValue)={\the\@tempcntb}% - \else - \advance\@tempcnta\@ne - \fi} - % - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={\@tempa}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={\@tempb}% - \AssociativeArray@Indexes(\AssociativeArrayNbValues)={\the\@tempcnta}% - \fi} - - % /HLComment?We change the way we draw each number of occurrences; - /HLMacro?\def\Draw@OneOccurrence;#1{% - \checkAssociativeArray@Indexes(#1)% - \pst@cnta=\cachedata - \checkAssociativeArray@Values(#1)% - \psdot(\the\pst@cnta,\cachedata) - \rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \DrawOccurrences{We are Wednesday} - - \PrintIndexes -\end{CenterExample} - -\makeatletter - -% To get in #2 the ASCII code of the #1 character -\def\Character@AsciiCode#1#2{\chardef#2=`#1\relax}% - -% A new "standard" array to store the sorted indexes -\newarray\AssociativeArray@Indexes - -% We redefine the macro to store an element in the associative array, -% to allow to sort it elements, using an additional array of indexes -\def\AssociativeArray(#1)=#2{% -\expandarrayelementtrue -\AssociativeArray@ElementFoundfalse -\edef\@tempa{#1}% -\edef\@tempb{#2}% -\Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \ifx\@tempa\cachedata - % This element already exist: we replace it current value - % \checkAssociativeArray@Values(\iValue)% Debug - % \typeout{In #1, replace `\cachedata'\space by `#2'}% Debug - \AssociativeArray@Values(\iValue)={\@tempb}% - \AssociativeArray@ElementFoundtrue - \multidostop - \fi} -\ifAssociativeArray@ElementFound -\else - % New element: we must insert it at it sorted position - \@tempcnta=\@ne - \expandafter\Character@AsciiCode\@tempa\@tempx - \Multido{\iValue=\@ne+\@ne}{\AssociativeArrayNbValues}{% - \checkAssociativeArray@Names(\iValue)% - \expandafter\Character@AsciiCode\cachedata\@tempy - \ifnum\@tempx<\@tempy - % The new element must be before this one: we will exchange their values - \checkAssociativeArray@Indexes(\iValue)% - \@tempcntb=\cachedata - \advance\@tempcntb\@ne - \AssociativeArray@Indexes(\iValue)={\the\@tempcntb}% - \else - \advance\@tempcnta\@ne - \fi} - % - \advance\AssociativeArrayNbValues\@ne - \AssociativeArray@Names(\AssociativeArrayNbValues)={\@tempa}% - \AssociativeArray@Values(\AssociativeArrayNbValues)={\@tempb}% - \AssociativeArray@Indexes(\AssociativeArrayNbValues)={\the\@tempcnta}% -\fi} - -% We change the way we draw each number of occurrences -\def\Draw@OneOccurrence#1{% -\checkAssociativeArray@Indexes(#1)% -\pst@cnta=\cachedata -\checkAssociativeArray@Values(#1)% -\psdot(\the\pst@cnta,\cachedata) -\rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - -\makeatother - -\begin{CenterExample} - \DrawOccurrences{Tuesday 8 February} -\end{CenterExample} - -\noindent Now, we can easily redefine the internal macro which plot each -occurrence, to obtain various kinds of graphics: - -\begin{CenterExample} - \makeatletter - - /HLMacro?\def\Draw@OneOccurrence;#1{% - \checkAssociativeArray@Indexes(#1)% - \pst@cnta=\cachedata - \checkAssociativeArray@Values(#1) - \psline[linestyle=dotted](\the\pst@cnta,0)(\the\pst@cnta,\cachedata) - \psdot(\the\pst@cnta,\cachedata) - \rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \psset{xunit=0.5,dotstyle=*,dotsize=0.3} - \DrawOccurrences{I do not believe that it can be correct} -\end{CenterExample} - -\begin{CenterExample} - \makeatletter - - \SpecialCoor - - /HLMacro?\def\Draw@OneOccurrence;#1{% - \checkAssociativeArray@Indexes(#1)% - \pst@cnta=\cachedata - \checkAssociativeArray@Values(#1)% - \pspolygon*[linecolor=red](! \the\pst@cnta\space 0.3 sub 0) - (! \the\pst@cnta\space 0.3 sub \cachedata) - (! \the\pst@cnta\space 0.3 add \cachedata) - (! \the\pst@cnta\space 0.3 add 0) - \rput[B](\the\pst@cnta,-0.5){\AssociativeArray@Names(#1)}} - - \makeatother - - \psset{xunit=0.5,ticks=y} - \DrawOccurrences{I don't know a better solution than this one} -\end{CenterExample} -\else - \PSTricksExampleNotShown -\fi % End \pstrickstrue - -\section{Thanks} - - I would like to thank Rolf Niepraschk \verb+<niepraschk@ptb.de>+ to have -carefully read a preliminary version of this document and to have sent me -several good advices to clarify and improve some points. - -\begin{thebibliography}{9} - \bibitem{SVB93} Stephan von \textsc{Bechtolsheim}, \emph{\TeX{} in - Practice}, four volumes, Springer-Verlag, New York, 1993 (see also - \url{CTAN: macros/tip/arraymac.tip}). - \bibitem{REPEAT} \RepeatPackage, by Victor \textsc{Eijkhout}, University of - Illinois, Urbana-Champaign, USA, \url{CTAN: macros/generic/eijkhout/repeat} - \bibitem{EG98} Philippe \textsc{Esperet} and Denis \textsc{Girou}, - \emph{Coloriage du pavage dit de Truchet}, Cahiers GUTenberg, Number~31, - December 98, pages 5-18, in french (see - \url{http://www.gutenberg.eu.org/pub/GUTenberg/publicationsPS/31-girou.ps.gz}). - \bibitem{ALDRATEX} \AlDraTeXPackage, by Eitan M. \textsc{Gurari}, Ohio State - University, Columbus, USA, \url{CTAN: graphics/dratex} (see also - \url{http://www.cis.ohio-state.edu/~gurari/systems.html}). - \bibitem{Gur94} Eitan M. \textsc{Gurari}, \emph{\TeX{} and \LaTeX: Drawing - and Literate Programming}, McGraw-Hill, New-York, 1994. - \bibitem{METAPOST} \MetaPostPackage, by John D. \textsc{Hobby}, AT\&T Bell - Laboratories, USA, \url{CTAN: graphics/metapost} (see also - \url{http://cm.bell-labs.com/who/hobby/MetaPost.html}). - \bibitem{FORMLETT} \FormLettPackage, by Zhuhan \textsc{Jiang}, University of - New England, Armidale, Australia, \url{CTAN: macros/generic/formlett.sty} (see - also \url{http://maths.une.edu.au/~zhuhan/util.html#computer}). - \bibitem{MULTIDO} \MultiDoPackage, by Timothy van \textsc{Zandt}, INSEAD, - Fontainebleau, France, \url{CTAN: macros/generic/multido} - \bibitem{PSTRICKS} \PSTricksPackage, by Timothy van \textsc{Zandt}, INSEAD, - Fontainebleau, France, \url{CTAN: graphics/pstricks} (see also - \url{http://www.tug.org/applications/PSTricks}). -\end{thebibliography} - -\end{document} |