How to randomize the order of (sub)sections?
Update -- The number of sections per chapter is used now to provide the correct range for the random generator. No random number is used twice within a chapter.
The usage is \section{Section title}[section content]
, the list is cleared each time a new chapter is used and displayed with \displaysections
, linking and labelling works, if the \label
is placed within the final optional argument.
The generalization to subsections is similar.
Addition about the uniqueness of the random number:
\NewDocumentCommand{\displaysections}{}{%
\f@rst=\@ne % Direct manipulation works ;-)
\l@st=\seq_count:N \chapterwise_seq%
\int_zero:N \l_tmpa_int
\seq_clear:N \l_tmpa_seq
\int_do_while:nn { \l_tmpa_int < \seq_count:N \chapterwise_seq} {
\rand%
\seq_if_in:NxF \l_tmpa_seq {\number\value{myrandcounter}} { %
\int_incr:N \l_tmpa_int
\seq_put_right:Nx \l_tmpa_seq {\number\value{myrandcounter}}
}
}
\seq_map_inline:Nn \l_tmpa_seq {%
\seq_item:Nn \chapterwise_seq {##1}
}
}
The \int_do_while:nn
loops runs until all sections are displayed. The current random number is stored into a list if it is not already in the list -- this way, only unique numbers are added. This is done with
\seq_if_in:NxF \l_tmpa_seq {\number\value{myrandcounter}} { %
\int_incr:N \l_tmpa_int
\seq_put_right:Nx \l_tmpa_seq {\number\value{myrandcounter}}
}
Now the code:
\documentclass{book}
\usepackage[seed=100,counter=myrandcounter,first=1,last=100]{lcg}
\usepackage{xpatch}
\usepackage{xparse}
\usepackage{blindtext} % Just for dummy text
\usepackage{hyperref}
\usepackage{cleveref}
\makeatletter
\ExplSyntaxOn
\seq_new:N \chapterwise_seq
\let\latex@@section\section
\RenewDocumentCommand{\section}{som+O{}}{%
\IfBooleanTF{#1}{%
\latex@@section*{#3}%
}{%
\IfValueTF{#2}{%
\seq_put_right:Nn \chapterwise_seq {\latex@@section[#2]{#3} #4}
}{%
\seq_put_right:Nn \chapterwise_seq {\latex@@section{#3} #4}
}
}
}
\xpretocmd{\chapter}{\seq_clear:N \chapterwise_seq}{}{}
\newcommand{\getnumofsections}{%
\seq_count:N \chapterwise_seq%
}
\newcounter{tempcntr}
\NewDocumentCommand{\displaysections}{}{%
\f@rst=\@ne % Direct manipulation works ;-)
\l@st=\seq_count:N \chapterwise_seq%
\int_zero:N \l_tmpa_int
\seq_clear:N \l_tmpa_seq
\int_do_while:nn { \l_tmpa_int < \seq_count:N \chapterwise_seq} {
\rand%
\seq_if_in:NxF \l_tmpa_seq {\number\value{myrandcounter}} { %
\int_incr:N \l_tmpa_int
\seq_put_right:Nx \l_tmpa_seq {\number\value{myrandcounter}}
}
}
\seq_map_inline:Nn \l_tmpa_seq {%
\seq_item:Nn \chapterwise_seq {##1}
}
}
\ExplSyntaxOff
\makeatother
\begin{document}
\chapter{First}
\section{A}[This is section A \label{Sec:A}]
\section{B}[This is section B -- in \ref{Sec:A}]
\section{C}[This is section C]
\typeout{Foo}
\displaysections
\typeout{Foo}
\chapter{Second}
\section{A}[This is another section A \label{Sec:AA}]
\section{B}[This is another section B -- in \ref{Sec:AA}]
\section{C}[This is another section C \label{Sec:CC} \subsection{Foo} \blindtext[50]]
\section{D}[This is another section D \label{Sec:DD}]
\section{E}[This is another section E -- in \nameref{Sec:A} we see]
\section{F}[This is another section F \label{Sec:FF} \subsection{Another Foo} \blindtext[10]]
\displaysections
\end{document}
This solution creates a list of filenames then reads them in random order.
\documentclass{report}
\usepackage{pgfmath}
\usepackage{lipsum}
\newcounter{index}[chapter]
\newcommand{\addfilename}[1]% #1=filename
{\stepcounter{index}%
\expandafter\xdef\csname section\theindex\endcsname{#1}}
\newcommand{\randomize}%
{\bgroup% use local definitions (\total, \temp)
\edef\total{\theindex}%
\setcounter{index}{0}%
\loop\stepcounter{index}% last loop does nothing
\edef\temp{\csname section\theindex\endcsname}%
\pgfmathparse{int((\total-\theindex)*rnd+\theindex)}%
\expandafter\xdef\csname section\theindex\endcsname{\csname section\pgfmathresult\endcsname}%
\expandafter\xdef\csname section\pgfmathresult\endcsname{\temp}%
\ifnum\value{index}<\total\relax \repeat
%
\setcounter{index}{0}%
\loop\stepcounter{index}%
\input{\csname section\theindex\endcsname}
\ifnum\value{index}<\total\relax \repeat
\egroup}
\begin{document}
\chapter{First}
\addfilename{sectionA}
\addfilename{sectionB}
\addfilename{sectionC}
\addfilename{sectionD}
\randomize
\chapter{Second}
\addfilename{sectionA}
\addfilename{sectionB}
\addfilename{sectionC}
\addfilename{sectionD}
\randomize
\end{document}
where file sectionA is
\section{This is section A}
\lipsum[1]
file sectionB is
\section{This is section B}
\lipsum[2]
and so on.
Note that the order changes each time you run it.