[Tex/LaTex] How to generate in LaTeX a list of random questions avoiding repetitions

listsrandomrandom numberstikz-pgf

How do I generate in LaTeX a list of random questions avoiding repetitions?

\documentclass{article}
\usepackage[pdftex]{exerquiz}
\usepackage{enumitem}
\usepackage{tikz}

\newcommand*{\ListOfTopics}{%
    AlgebraQuestions,%
    TrigQuestions%
}%
\pgfmathdeclarerandomlist{AlgebraQuestions}{%
 {AlgebraQ1}%
 {AlgebraQ2}%    
 {AlgebraQ3}%          
}%
\pgfmathdeclarerandomlist{TrigQuestions}{%
    {TrigQ1}%
    {TrigQ2}%
    {TrigQ3}%
}%
\newcommand*{\NumberOfQuizes}{3}%

\begin{document}

\foreach \QuizNumber in {1,...,\NumberOfQuizes} {%
\section{Вариант}
   \noindent\textbf{\Large Quiz Number \QuizNumber}%
    \begin{enumerate}

    \foreach \Topic in \ListOfTopics {%
        \pgfmathrandomitem{\RandomQuestion}{\Topic} 
        \item Random Question from Topic='\Topic': 
            \textbf{\Large\RandomQuestion}%
    }%
    \end{enumerate}
}%
\end{document}

I read that I can use that, but how to adapt it?

\def\prunelist#1{%
\expandafter\edef\csname pgfmath@randomlist@#1\endcsname
        {\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}
\count@\pgfmath@randomtemp 
\loop
\expandafter\let
\csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
\csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
\ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
\advance\count@\@ne
\repeat}

Best Answer

For a LaTeX/pgfmath solution I'd go with something like the code shown below. The code is somewhat impenetrable, but it is unfortunately unavoidable. As random list stuff is all assigned globally, it is necessary to also introduce a command to copy random lists. Possibly with LuaLaTeX and tables it would be easier.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{pgfmath,pgffor}


\makeatletter
\def\pgfmathrandomitemwithoutreplacement#1#2{%
    \pgfmath@ifundefined{pgfmath@randomlist@#2}{\pgfmath@error{Unknown random list `#2'}}{%
        \edef\pgfmath@randomlistlength{\csname pgfmath@randomlist@#2\endcsname}%
        \ifnum\pgfmath@randomlistlength>0\relax%
            \pgfmathrandominteger{\pgfmath@randomtemp}{1}{\pgfmath@randomlistlength}%
            \def\pgfmath@marshal{\def#1}%
            \expandafter\expandafter\expandafter\pgfmath@marshal\expandafter\expandafter\expandafter{\csname pgfmath@randomlist@#2@\pgfmath@randomtemp\endcsname}%
            % Now prune.
            \c@pgfmath@counta=\pgfmath@randomtemp\relax%
            \c@pgfmath@countb=\c@pgfmath@counta%
            \advance\c@pgfmath@countb by1\relax%
            \pgfmathloop%
            \ifnum\c@pgfmath@counta=\pgfmath@randomlistlength\relax%
            \else%
                \def\pgfmath@marshal{\expandafter\global\expandafter\let\csname pgfmath@randomlist@#2@\the\c@pgfmath@counta\endcsname=}%
                \expandafter\pgfmath@marshal\csname pgfmath@randomlist@#2@\the\c@pgfmath@countb\endcsname%
                \advance\c@pgfmath@counta by1\relax%
                \advance\c@pgfmath@countb by1\relax%
            \repeatpgfmathloop%
            \advance\c@pgfmath@counta by-1\relax%
            \expandafter\xdef\csname pgfmath@randomlist@#2\endcsname{\the\c@pgfmath@counta}%        
        \else%
            \pgfmath@error{Random list `#2' is empty}%
        \fi%        
    }}


\def\pgfmathrandomlistcopy#1#2{%
    \pgfmath@ifundefined{pgfmath@randomlist@#2}{\pgfmath@error{Unknown random list `#2'}}{%
        \edef\pgfmath@randomlistlength{\csname pgfmath@randomlist@#2\endcsname}%
        \pgfmathloop%
        \ifnum\pgfmathcounter>\pgfmath@randomlistlength\relax%
        \else%
            \def\pgfmath@marshal{\expandafter\global\expandafter\let\csname pgfmath@randomlist@#1@\pgfmathcounter\endcsname=}%
            \expandafter\pgfmath@marshal\csname pgfmath@randomlist@#2@\pgfmathcounter\endcsname%
        \repeatpgfmathloop%
        \expandafter\xdef\csname pgfmath@randomlist@#1\endcsname{\pgfmath@randomlistlength}%
    }%  
}
\makeatother

\begin{document}

\newcommand*{\ListOfTopics}{%
    AlgebraQuestions,%
    TrigQuestions%
}%
\pgfmathdeclarerandomlist{AlgebraQuestionsMaster}{%
 {AlgebraQ1}%
 {AlgebraQ2}%    
 {AlgebraQ3}%          
}%
\pgfmathdeclarerandomlist{TrigQuestionsMaster}{%
    {TrigQ1}%
    {TrigQ2}%
    {TrigQ3}%
}%
\newcommand*{\NumberOfQuizes}{3}%


\pgfmathrandomlistcopy{AlgebraQuestions}{AlgebraQuestionsMaster}
\pgfmathrandomlistcopy{TrigQuestions}{TrigQuestionsMaster}

\foreach \QuizNumber in {1,...,\NumberOfQuizes} {%
\section{Option}% <- correct translation?
   \noindent\textbf{\Large Quiz Number \QuizNumber}%
    \begin{enumerate}
    \foreach \Topic in \ListOfTopics {%
        \pgfmathrandomitemwithoutreplacement{\RandomQuestion}{\Topic} 
        \item Random Question from Topic='\Topic': 
            \textbf{\Large\RandomQuestion}%
    }%
    \end{enumerate}
}%

\end{document}

And to give a more graphical demonstration, consider following code (with \usepackage{tikz} in the preamble):

\pgfmathdeclarerandomlist{some numbers}{{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}}
\pgfmathrandomlistcopy{tmp}{some numbers}

\begin{tikzpicture}
    \foreach \i in {1, ..., 10}{
        \pgfmathrandomitemwithoutreplacement\j{tmp}
        \node (i-\i) at (\i, 0) {\i};
        \node (j-\j) at (\j, 2) {\j};
        \draw [->] (i-\i) -- (j-\j);
    }
\end{tikzpicture}

enter image description here