8

With a group of teachers friends we are compiling the national and international tests applied in my country from 1980. These are "multiple choice" tests, with most of the tests already written using the enumerate package or the enumitem package. A total of 50 tests each with 60 or 80 questions.

In order to be able to save the keys to each question, without having to make any more modifications to the files, I have created an environment mchoice and two commands \keych and \keytest using \label...\reffor save keys of each question using xparse,pgffor,refcount, enumitem, hyperref and tcolorbox package.

As I will often use \label (about 4000 times) I would like to know if TeX (latex or pdflatex) can process it, that is, it will not give me a memory error.

I tried searching for a "perl hash style" to save the keys to each question, (whitout label ref) something similar to what I proposed in https://tex.stackexchange.com/a/215628/7832 (save value in list) but I did not get it to work.

Grateful in advance

% file mchoice.tex
% arara: latex: {draft: yes}
% arara: latex
% arara: dvips
% arara: ps2pdf
% arara: clean: { files:[mchoice.aux, mchoice.log, mchoice.out,mchoice.dvi,mchoice.ps] }
\documentclass{article}
\usepackage{enumitem}
\usepackage{multicol}
\usepackage{pgffor}
\usepackage[colorlinks]{hyperref}
\usepackage{refcount}
\usepackage{tcolorbox}
\tcbuselibrary{many}

% Set key for multicols in enumitem \SetEnumitemKey{columns}{before=\begin{multicols}{#1},after=\end{multicols}}%

% Custom label for save choice key \makeatletter \newcommand{\customlabel}[2]{% \protected@write @auxout {}{\string \newlabel {#1}{{#2}{\thepage}{#2}{#1}{}} }% \hypertarget{#1}{}% } \makeatother

% Create a environment mchoice, scope enumerate and \keych \NewDocumentEnvironment{mchoice}{m}{% \label{#1} % values for multicols \setlength{\multicolsep}{5.0pt plus 2.0pt minus 1.5pt} % values for enumitem \setenumerate{parsep=3.5pt,partopsep=3.5pt,topsep=3.5pt,labelsep=5pt, leftmargin=, itemsep=0pt,widest=80}% \setenumerate[1]{labelsep=5pt,itemsep=1pt,label=\arabic.} \setenumerate[2]{leftmargin=16pt,nosep,itemsep=0pt,label=\Alph*)} % Command to save key choice \NewDocumentCommand\keych{o}{% \IfNoValueTF{##1}% {\customlabel{#1:\arabic{enumi}}{\Alph{enumii}}}% {\customlabel{#1:\arabic{enumi}}{##1}}}% close \keych }% {% \customlabel{max:#1}{\arabic{enumi}} }% close mchoice

% Create a command to all key for test % #1 : pass to tcolorbox % #2 : name % #3 : ref % #4 : columns \newcounter{last} \DeclareTotalTColorBox{\keytest}{ O{} m m O{4}} { size=small,top=-1mm, left=0mm,width=\columnwidth,% adjusted title=center,halign title=center,title filled,fontupper=\small,% fonttitle=\small\sffamily,adjusted title={#2},center title,#1} {% \begin{enumerate}[columns=#4,leftmargin=15pt,labelsep=3pt,font=\small,nosep,widest=25]% \small \setlength{\columnsep}{0pt} \setcounterref{last}{max:#3} \foreach \x in {1,...,\value{last}} { \item \ref{#3:\x} } \end{enumerate} }%

\begin{document} \section{National Prov}

\begin{mchoice}{paa-1985-a} \begin{center} \textbf{PAA 1985 (A)} \end{center} \begin{enumerate} \item First type of questions \begin{enumerate}% \item value \item value \item value \item correct \keych \item value \end{enumerate} \item Second type of questions \begin{enumerate}[leftmargin=3pc,label=\Roman.] \item $2\alpha+2\delta=90^{\circ}$ \item $\alpha=\delta$ \item $\angle EDF=45^{\circ}$ \end{enumerate} \begin{enumerate}[columns=2]% \item I only \item II only \keych \item I and II only \item I and III only \item I, II, and III \end{enumerate} \item Third type of questions \begin{enumerate}[leftmargin=3pc,label=(\arabic)] \item $2\alpha+2\delta=90^{\circ}$ \item $\angle EDF=45^{\circ}$ \end{enumerate} \begin{enumerate}[columns=2]%
\item Altenativa A \item Altenativa B \keych \item Altenativa C \item Altenativa D \item Altenativa E \end{enumerate} \item Fourth type of questions (these need manual tuning for alternatives, usually carrying pictures or tables) \begin{center} \noindent \hspace*{0.75cm}\includegraphics[scale=0.15]{example-image-b} \end{center}

\begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline A) \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline B) \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline C) \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline D) \keych[D] \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline E) \end{minipage} \item Fifth type of questions, a problem with numerical response \keych[$2]

\end{enumerate} \end{mchoice}

\begin{mchoice}{paa-1985-b} \begin{center} \textbf{PAA 1985 (B)} \end{center} \begin{enumerate} \item First type of questions \begin{enumerate}% \item value \item correct \keych \item value \item value \item value \end{enumerate} \item Second type of questions \begin{enumerate}[leftmargin=3pc,label=\Roman.] \item $2\alpha+2\delta=90^{\circ}$ \item $\alpha=\delta$ \item $\angle EDF=45^{\circ}$ \end{enumerate} \begin{enumerate}[columns=2]% \item I only \item II only \item I and II only \item I and III only \keych \item I, II, and III \end{enumerate} \item Third type of questions \begin{enumerate}[leftmargin=3pc,label=(\arabic)] \item $2\alpha+2\delta=90^{\circ}$ \item $\angle EDF=45^{\circ}$ \end{enumerate} \begin{enumerate}[columns=2]%
\item Altenativa A \item Altenativa B \item Altenativa C \item Altenativa D \keych \item Altenativa E \end{enumerate} \item Fourth type of questions (these need manual tuning for alternatives, usually carrying pictures or tables) \begin{center} \noindent \hspace*{0.75cm}\includegraphics[scale=0.15]{example-image-b} \end{center}

\begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline A) \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline B) \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline C) \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline D) \end{minipage} \begin{minipage}{0.2\textwidth} \centering \includegraphics[scale=0.15]{example-image-a}\newline E) \keych[E] \end{minipage} \item Fifth type of questions, a problem with numerical response \keych[$3]

\end{enumerate} \end{mchoice}

\section{Answer key} \begin{multicols}{2} \setlength{\columnsep}{0pt} \keytest{PAA 1985 (form A)}{paa-1985-a}[5] \keytest{PAA 1985 (form B)}{paa-1985-b}[5] \end{multicols} \end{document}

Some screen Model Test Continue

  • Interesting question – Moriambar Apr 09 '17 at 16:28
  • 3
    Every \label will create a (csname-)command, so too much \label's can overflow the string pool but imho 4000 shouldn't be a problem. See e.g. https://tex.stackexchange.com/questions/316999/release-space-in-the-string-pool – Ulrike Fischer Apr 09 '17 at 16:41
  • I see, I've read about the increase in hash size in the book "The Latex Companion". I think I do not really need to use the label ref system for what I want, could it be done using a kind of array like in the solution you put in the question http://tex.stackexchange.com/a/215628/7832 ? – Pablo González L Apr 09 '17 at 16:55
  • @ChristianHupfer: I think 65536, i.e. 2^16 labels should be safe ... That number is the one that interested me .... – Pablo González L Apr 09 '17 at 16:57
  • @PabloGonzálezL: Forget my comment –  Apr 09 '17 at 17:04
  • Avoiding labels wouldn't change much: You want to store data and as pdflatex doesn't allocate memory dynamically you always can run out of memory. But as I said 4000 isn't much today. – Ulrike Fischer Apr 09 '17 at 17:58
  • Great, I had been breaking head with the idea that label/ref abuse would cause a memory problem, and that saving the data in a list (a hash/array in my perl mind) would make the process faster . Thankful for everything. – Pablo González L Apr 09 '17 at 18:05
  • @UlrikeFischer "But as I said 4000 isn't much today." I agree. But the first version of TeX (not even LaTeX) I used was on an IBM PC with half a megabyte of RAM (not even the full 640k) and a "huge" 10Mb hard disk (note, "Mb" is not a typo). The "rules" have changed since those days! If you were lucky, it would compile your document at about 2 pages per minute. – alephzero Apr 09 '17 at 20:24
  • @PabloGonzálezL the main point about \label is that it writes to file so the definitions can be read at the start of the next run, to allow forward references, but it would seem that you never need forward references here so you could avoid writing 4000 lines to the aux file and reading them back. which will slow things down even if it does not stress memory limits. – David Carlisle Apr 09 '17 at 22:02
  • @DavidCarlisle: It's exactly what i'm thinking, my original idea was that, but, I could not adapt the idea of saving the keys of the questions in a list, get the length of the list and then do a "loop for" on these. As you mentioned below, TeX does not have array :), maybe should I ask a new question? – Pablo González L Apr 09 '17 at 22:38
  • New question, changue label/ref for data save in an array (http://tex.stackexchange.com/questions/363961/change-the-use-of-label-ref-by-data-save-in-an-array) – Pablo González L Apr 09 '17 at 23:18
  • "You could avoid writing 4000 lines"... I would benchmark this, before you decide to "do it anyway". Unless your computer only has a small amount of RAM, quite likely writing the aux file will be done asynchronously by the OS (even Windows 98 used to do that!) and reading it back will just be reading the data that was cached into RAM when it was written. Even if there is 100 bytes of aux data per label, the 4000 lines is less than half a megabyte of data, which is in the "too small to bother about" category on a modern PC - on a decent hard disk, that's about 0.02 seconds of "time wasted". – alephzero Apr 10 '17 at 02:59
  • @ alephzero: Interesting, the truth is not as it saves and analyzes the data in memory TeX, but, if a data can be worked in memory, what to write it ?, although the access to the physical disk is quite fast, personally, I prefer to avoid Write temporary files (or record timelines) if I can pull the dat directly from memory. Actually, I'm a little lost in this ... in my mind (and because of the little training in programming that I have) I think it is better to avoid writing in the auxiliary file – Pablo González L Apr 10 '17 at 03:43

2 Answers2

5

Look at the end of the .log file, where it says "Here is how much of TeX's memory you used:..."

4,000 labels should be no problem at all with a reasonably modern TeX implementation, unless you use insanely long labels. In fact 40,000 labels in a document would probably work fine. (FWIW, I vaguely remember running out of memory at about 60,000 once, a few years ago).

There is usually some way to increase the memory allocation if you need to. The way to do that depends on what version of TeX you have installed, so you need to read the documentation.

alephzero
  • 1,940
  • Many thanks for the clarification, I use TexLive 2016, in a machine with fedora 25 (x64) ... should not be a problem according to your answer. I assume that the more \label, the compilation process will take longer ... I will try to save the keys in an array to skip the problem and not abuse the label. – Pablo González L Apr 09 '17 at 17:55
  • 1
    @PabloGonzálezL tex does not have arrays. – David Carlisle Apr 09 '17 at 18:11
3

the number of labels is probably not an issue these days but as you do not need forward references there is no need to write all that data to a file to be read back, you can just save the data in commands without writing to the aux file.

% file mchoice.tex
% arara: latex: {draft: yes}
% arara: latex
% arara: dvips
% arara: ps2pdf
% arara: clean: { files:[mchoice.aux, mchoice.log, mchoice.out,mchoice.dvi,mchoice.ps] }
\documentclass{article}
\usepackage{enumitem}
\usepackage{multicol}
\usepackage{pgffor}
\usepackage[colorlinks]{hyperref}
\usepackage{refcount}
\usepackage{tcolorbox}
\tcbuselibrary{many}

% Set key for multicols in enumitem
\SetEnumitemKey{columns}{before=\begin{multicols}{#1},after=\end{multicols}}%

% Custom label for save choice key
\makeatletter
\newcommand{\customlabel}[2]{%
   \expandafter\xdef\csname#1\endcsname{#2}%
   \hypertarget{#1}{}%
}
\makeatother

% Create a environment mchoice, scope enumerate and \keych
\NewDocumentEnvironment{mchoice}{m}{%
\label{#1}
% values for multicols 
\setlength{\multicolsep}{5.0pt plus 2.0pt minus 1.5pt}
% values for enumitem
\setenumerate{parsep=3.5pt,partopsep=3.5pt,topsep=3.5pt,labelsep=5pt, leftmargin=*, itemsep=0pt,widest=80}%
\setenumerate[1]{labelsep=5pt,itemsep=1pt,label=\arabic*.}
\setenumerate[2]{leftmargin=16pt,nosep,itemsep=0pt,label=\Alph*)}
% Command to save key choice
\NewDocumentCommand\keych{o}{%
\IfNoValueTF{##1}%
    {\customlabel{#1:\arabic{enumi}}{\Alph{enumii}}}%
    {\customlabel{#1:\arabic{enumi}}{\string##1}}}% close \keych
}%
{%
\customlabel{max:#1}{\arabic{enumi}}%
}% close mchoice

% Create a command to all key for test
% #1 : pass to tcolorbox
% #2 : name
% #3 : ref
% #4 : columns
\newcounter{last}
\DeclareTotalTColorBox{\keytest}{ O{} m m O{4}}
{ size=small,top=-1mm, left=0mm,width=\columnwidth,%
  adjusted title=center,halign title=center,title filled,fontupper=\small,%
  fonttitle=\small\sffamily,adjusted title={#2},center title,#1}
  {% 
  \begin{enumerate}[columns=#4,leftmargin=15pt,labelsep=3pt,font=\small,nosep,widest=25]%
  \small
  \setlength{\columnsep}{0pt}%
   \edef\tmp{\noexpand\foreach \noexpand\x in {1,...,\csname max:#3\endcsname}}%
   \tmp{%
    \item \hyperlink{#3:\x}{\csname#3:\x\endcsname}%
    }
  \end{enumerate}%
}%

\begin{document}
\section{National Prov}

\begin{mchoice}{paa-1985-a}
\begin{center}
\textbf{PAA 1985 (A)}
\end{center}
\begin{enumerate}
\item First type of questions
    \begin{enumerate}% 
        \item value 
        \item value 
        \item value
        \item correct \keych
        \item value 
    \end{enumerate}
\item Second type of questions
        \begin{enumerate}[leftmargin=3pc,label=\Roman*.]
            \item $2\alpha+2\delta=90^{\circ}$
            \item $\alpha=\delta$ 
            \item $\angle EDF=45^{\circ}$
        \end{enumerate}
\begin{enumerate}[columns=2]% 
        \item I only 
        \item II only \keych
        \item I and II only
        \item I and III only 
        \item I, II, and III
\end{enumerate}
\item Third type of questions
        \begin{enumerate}[leftmargin=3pc,label=(\arabic*)]
            \item $2\alpha+2\delta=90^{\circ}$
            \item $\angle EDF=45^{\circ}$
        \end{enumerate}
    \begin{enumerate}[columns=2]%  
        \item Altenativa A 
        \item Altenativa B \keych
        \item Altenativa C
        \item Altenativa D
        \item Altenativa E 
    \end{enumerate}
\item Fourth type of questions (these need manual tuning for alternatives, 
      usually carrying pictures or tables)
\begin{center}
\noindent
\hspace*{0.75cm}\includegraphics[scale=0.15]{example-image-b}
\end{center}

\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline A)
\end{minipage}
\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline B)
\end{minipage}
\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline C)
\end{minipage}
\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline D) \keych[D]
\end{minipage}
\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline E)
\end{minipage}
\item Fifth type of questions, a problem with numerical response \keych[\$2]

\end{enumerate}
\end{mchoice}


\begin{mchoice}{paa-1985-b}
\begin{center}
\textbf{PAA 1985 (B)}
\end{center}
\begin{enumerate}
\item First type of questions
    \begin{enumerate}% 
        \item value 
        \item correct \keych
        \item value 
        \item value
        \item value 
    \end{enumerate}
\item Second type of questions
        \begin{enumerate}[leftmargin=3pc,label=\Roman*.]
            \item $2\alpha+2\delta=90^{\circ}$
            \item $\alpha=\delta$ 
            \item $\angle EDF=45^{\circ}$
        \end{enumerate}
\begin{enumerate}[columns=2]% 
        \item I only 
        \item II only 
        \item I and II only
        \item I and III only \keych
        \item I, II, and III
\end{enumerate}
\item Third type of questions
        \begin{enumerate}[leftmargin=3pc,label=(\arabic*)]
            \item $2\alpha+2\delta=90^{\circ}$
            \item $\angle EDF=45^{\circ}$
        \end{enumerate}
    \begin{enumerate}[columns=2]%  
        \item Altenativa A 
        \item Altenativa B 
        \item Altenativa C
        \item Altenativa D \keych
        \item Altenativa E 
    \end{enumerate}
\item Fourth type of questions (these need manual tuning for alternatives, 
      usually carrying pictures or tables)
\begin{center}
\noindent
\hspace*{0.75cm}\includegraphics[scale=0.15]{example-image-b}
\end{center}

\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline A)
\end{minipage}
\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline B)
\end{minipage}
\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline C)
\end{minipage}
\begin{minipage}{0.2\textwidth} \centering
\includegraphics[scale=0.15]{example-image-a}\newline D) 
\end{minipage}
\begin{minipage}{0.2\textwidth}
\centering
\includegraphics[scale=0.15]{example-image-a}\newline E) \keych[E]
\end{minipage}
\item Fifth type of questions, a problem with numerical response \keych[\$3]

\end{enumerate}
\end{mchoice}

\section{Answer key}
\begin{multicols}{2}
\setlength{\columnsep}{0pt} 
\keytest{PAA 1985 (form A)}{paa-1985-a}[5]
\keytest{PAA 1985 (form B)}{paa-1985-b}[5]
\end{multicols}
\end{document} 
David Carlisle
  • 757,742
  • I'll leave this here for reference but this answer posted also to a followup question i saw after posting this. – David Carlisle Apr 09 '17 at 23:37
  • Cool! What modification should I make to the code to add special characters, subscripts and superscripts to the keych argument? – FrozenCore Nov 12 '21 at 13:03