6

How would you randomize the order of sections in a chapter (or subsection in a section)? I would type them in the order A, B, C, ..., but in the rendered document they should appear as 1=F, 2=Y, 3=C, etc. Thus they appear numbered starting with 1, but that is not the order I write them in the source file. Crossreferences should use the "new" numbering 1 to whatever and never the original one.

Rationale: I am writing a "game book", that is a story where the reader can decide what is going on by reading certain sections. E.g. section 7 might read "You are at a fork of the road. To go left read section 29, to go right read section 4.". To avoid judgement by the player which solution would be better, the order is totally random.

So far I used a manual semi-random approach and added each new section where I felt it should go. But it is tricky to avoid that choices are too close together (or worse: next to each other), especially if they get rearranged during writing. Also this is cumbersome as I can't order the sections in a way it helps my while writing (e.g. cluster by chapter/scene). And we are talking 300+ sections here.

I would like to avoid LuaLaTex and use XeLaTeX.

Bonus question: Ideally there would be a seed to this randomization, so it stays the same as long as the amount of sections does not change, or I explicitly change the seed.

  • 1
    I think, this is possible if the relevant sections are in several files and those being input with a random scheme that uses the same rand seed, otherwise the ordering (and labeling) would be different in each run – user31729 Feb 26 '16 at 15:58
  • I've thought of putting the sections in a file, and use shell scripts to split+rearrange them, but that feels like a workaround and is not so platform independet. So I still hope this can be done somehow within LaTeX. Individual files would be too much of a hassle to work on. – TeXter Feb 26 '16 at 16:00
  • Well, you know, that \section{A}...\section{B} fixes the order of the text in which they appear – user31729 Feb 26 '16 at 16:02
  • Why don't you just hyperlink the whole thing? You can divide the whole thing into many files, or use one file with all the optional details in doubly linked appendixes. See elfsoft2000.com/acoustic/enclosure.pdf – John Kormylo Feb 26 '16 at 17:07
  • This will be a printed book. – TeXter Feb 26 '16 at 17:09
5

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}

enter image description here

enter image description here

  • This looks very good and even supports multiple chapters with independent random subsections. Since my TeX-fu is not good enough: can you briefly explain how this solution guarantees no duplicates are picked within a chapter? I guess I have to manually select a first/last for lcg that is large enough that it fits all sections? – TeXter Mar 1 '16 at 16:15
  • @TeXter: Regarding the first and the last random number; You may set them in the beginning, large enough, but I think my code does not need them at all, as it determines the range before it uses \displaysection. Regarding the uniqueness of the random number, I will add an explanation to the post – user31729 Mar 1 '16 at 16:22
3

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.

  • This solution seems to do something different. It keeps the order of sections of the original document, but just gives it random section numbers. That is not what I intended. I would need in your screenshot that it reads: First -> 1.A normally 1.3, 1.B normally 1.1 1.C normally 1.5 etc. (the actual section numers are not important, they will be hidden anyway, but the random order of the content is) – TeXter Mar 1 '16 at 16:04
  • Could you put the source for each section into a different file? Then all one has to do is read the files in a random order. – John Kormylo Mar 1 '16 at 16:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.