Random Page Numbers
This uses the specified permutation within range, if you have more pages than that it reverts to normal, so you can always modify the definition at the end once you know how many pages you have
\documentclass{book}
\renewcommand\thepage{%
\ifcase\value{page}%
0\or
4\or
1\or
2\or
5\or
6\or
3\else
\arabic{page}%
\fi}
\begin{document}
\tableofcontents
\chapter{Intro}
\section{Zzzz}aaaa
\section{Zzzzz}aaaa \clearpage bbbb
\section{Zzzzz}aaaa
\chapter{Something}
\section{Zzzz zzz}aaaa
\section{Zzzzzz zzz}aaaa \clearpage bbbb
\section{Zzzzzzz zzz}aaaa
\end{document}
Just for fun an implementation that doesn't require external programs and just needs two LaTeX runs. However, the pages will change at every subsequent run.
\documentclass{article}
\usepackage{xparse}
\usepackage{zref-user,zref-abspage,atveryend}
\usepackage{kantlipsum}
% Coerce zref into not adding the last page number in the .aux file
% which would always issue the warning that labels have changed
\makeatletter
\zref@newlist{lastabs}
\zref@addprop{lastabs}{abspage}
\AfterLastShipout{%
\if@filesw
\begingroup
\advance\c@page\m@ne
\toks@\expandafter{\Z@L@lastabs}%
\expandafter\zref@wrapper@immediate\expandafter{%
\expandafter\ZREF@label\expandafter{\the\toks@}{LastAbsPage}%
}%
\endgroup
\fi
}
\makeatother
\ExplSyntaxOn
\cs_set_eq:Nc \zref_extract:nn { zref@extract }
% a variant of the Knuth shuffle algorithm as implemented
% in https://tex.stackexchange.com/a/224559/4427
\cs_new:Nn \knuthshuffle_get_random:Nnn
{
\int_set:Nn #1 { \fp_eval:n { randint(#2,#3) } }
}
\tl_new:N \l_knuthshuffle_tempa_tl
\tl_new:N \l_knuthshuffle_tempb_tl
\int_new:N \l_knuthshuffle_random_int
\prop_new:N \l_knuthshuffle_newperm_prop
\prop_new:N \g_knuthshuffle_identity_prop % the identity
\seq_new:N \g_knuthshuffle_permutation_seq
\cs_new_protected:Nn \knuthshuffle_generate:n
{
\prop_set_eq:NN \l_knuthshuffle_newperm_prop \g_knuthshuffle_identity_prop
\int_step_inline:nnnn { #1 } { -1 } { 2 }
{
\knuthshuffle_get_random:Nnn \l_knuthshuffle_random_int { 1 } { ##1 }
\prop_get:NnN \l_knuthshuffle_newperm_prop { ##1 } \l_knuthshuffle_tempa_tl
\prop_get:NVN \l_knuthshuffle_newperm_prop \l_knuthshuffle_random_int \l_knuthshuffle_tempb_tl
\prop_put:NnV \l_knuthshuffle_newperm_prop { ##1 } \l_knuthshuffle_tempb_tl
\prop_put:NVV \l_knuthshuffle_newperm_prop \l_knuthshuffle_random_int \l_knuthshuffle_tempa_tl
}
\seq_clear:N \g_knuthshuffle_permutation_seq
\int_step_inline:nnnn { 1 } { 1 } { #1 }
{
\seq_gput_right:Nx \g_knuthshuffle_permutation_seq
{
\prop_item:Nn \l_knuthshuffle_newperm_prop { ##1 }
}
}
%\seq_show:N \g_knuthshuffle_permutation_seq % for debugging
}
\cs_generate_variant:Nn \knuthshuffle_generate:n { x }
\AtBeginDocument
{
\int_compare:nT { \zref_extract:nn {LastAbsPage}{abspage} > 0 }
{
\int_step_inline:nnnn { 1 } { 1 } { \zref_extract:nn {LastAbsPage}{abspage} }
{
\prop_gput:Nnn \g_knuthshuffle_identity_prop { #1 } { #1 }
}
\knuthshuffle_generate:n { \zref_extract:nn {LastAbsPage}{abspage} }
\renewcommand{\thepage}{\randomarabic{page}}
}
}
\NewExpandableDocumentCommand{\randomarabic}{m}
{
\seq_item:Nn \g_knuthshuffle_permutation_seq { \value{#1} }
}
\ExplSyntaxOff
\begin{document}
\kant[1-102]
\ExplSyntaxOn
% for showing the used page numbers
\seq_use:Nn \g_knuthshuffle_permutation_seq { ,~ }
\ExplSyntaxOff
\end{document}
At the end the sequence of the used page numbers has been added by way of example.
Here's the bottom of the last page.
A more complex strategy can cope also with the table of contents. Now the random sequence is only computed if the number of pages has changed since the last LaTeX run, otherwise the previous sequence is used.
\documentclass{article}
\usepackage{xparse}
\usepackage{zref-abspage,atveryend}
\usepackage{kantlipsum}
\makeatletter
\zref@newlist{lastabs}
\zref@addprop{lastabs}{abspage}
\AfterLastShipout{%
\if@filesw
\begingroup
\advance\c@page\m@ne
\toks@\expandafter{\Z@L@lastabs}%
\expandafter\zref@wrapper@immediate\expandafter{%
\expandafter\ZREF@label\expandafter{\the\toks@}{LastAbsPage}%
}%
\endgroup
\fi
}
\makeatother
\ExplSyntaxOn
\cs_set_eq:Nc \zref_extract:nn { zref@extract }
\cs_new:Nn \knuthshuffle_get_random:Nnn
{
\int_set:Nn #1 { \fp_eval:n { randint(#2,#3) } }
}
\tl_new:N \l_knuthshuffle_tempa_tl
\tl_new:N \l_knuthshuffle_tempb_tl
\int_new:N \l_knuthshuffle_random_int
\prop_new:N \l_knuthshuffle_newperm_prop
\prop_new:N \g_knuthshuffle_identity_prop % the identity
\seq_new:N \g_knuthshuffle_permutation_seq
\cs_new_protected:Nn \knuthshuffle_generate:n
{
\prop_set_eq:NN \l_knuthshuffle_newperm_prop \g_knuthshuffle_identity_prop
\int_step_inline:nnnn { #1 } { -1 } { 2 }
{
\knuthshuffle_get_random:Nnn \l_knuthshuffle_random_int { 1 } { ##1 }
\prop_get:NnN \l_knuthshuffle_newperm_prop { ##1 } \l_knuthshuffle_tempa_tl
\prop_get:NVN \l_knuthshuffle_newperm_prop \l_knuthshuffle_random_int \l_knuthshuffle_tempb_tl
\prop_put:NnV \l_knuthshuffle_newperm_prop { ##1 } \l_knuthshuffle_tempb_tl
\prop_put:NVV \l_knuthshuffle_newperm_prop \l_knuthshuffle_random_int \l_knuthshuffle_tempa_tl
}
\seq_clear:N \g_knuthshuffle_permutation_seq
\int_step_inline:nnnn { 1 } { 1 } { #1 }
{
\seq_gput_right:Nx \g_knuthshuffle_permutation_seq
{
\prop_item:Nn \l_knuthshuffle_newperm_prop { ##1 }
}
}
%\seq_show:N \g_knuthshuffle_permutation_seq % for debugging
}
\cs_generate_variant:Nn \knuthshuffle_generate:n { x }
\AtBeginDocument
{
\seq_if_empty:NT \g_knuthshuffle_permutation_seq
{
\int_compare:nT { \zref_extract:nn {LastAbsPage}{abspage} > 0 }
{
\int_step_inline:nnnn { 1 } { 1 } { \zref_extract:nn {LastAbsPage}{abspage} }
{
\prop_gput:Nnn \g_knuthshuffle_identity_prop { #1 } { #1 }
}
\knuthshuffle_generate:n { \zref_extract:nn {LastAbsPage}{abspage} }
}
}
\renewcommand{\thepage}{\randomarabic{page}}
}
\AfterLastShipout
{
\int_compare:nT { \value{abspage} = \zref_extract:nn {LastAbsPage}{abspage} }
{
\iow_now:cx { @auxout }
{
\randompagesequence
{ \zref_extract:nn {LastAbsPage}{abspage} }
{ \seq_use:Nn \g_knuthshuffle_permutation_seq { , } }
}
}
}
\cs_new_protected:Npn \randompagesequence #1 #2
{
\int_compare:nT { #1 = \zref_extract:nn {LastAbsPage}{abspage} }
{
\seq_gset_from_clist:Nn \g_knuthshuffle_permutation_seq { #2 }
}
}
\NewExpandableDocumentCommand{\randomarabic}{m}
{
\seq_item:Nn \g_knuthshuffle_permutation_seq { \value{#1} }
}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\seq_show:N \g_knuthshuffle_permutation_seq
\ExplSyntaxOff
\tableofcontents
\section{One}
\kant[1-20]
\section{Two}
\kant[21-30]
\section{Three}
\kant[31-53]
\ExplSyntaxOn
% for showing the used page numbers
\seq_use:Nn \g_knuthshuffle_permutation_seq { ,~ }
\ExplSyntaxOff
\end{document}
Well, just to play around with it: A solution with expl3
with the only drawback that it will not check for an existing page with that number. The max page number can be set in \l__blob_int
.
\documentclass{book}
\usepackage{expl3}
\ExplSyntaxOn
\clist_new:N \l__quack_clist
\int_new:N \l__blub_int
\int_gset:Nn \l__blub_int {0}
\int_new:N \l__blob_int
\int_gset:Nn \l__blob_int {10}
\int_do_while:nn {\l__blub_int < \l__blob_int}
{
\clist_put_right:NV \l__quack_clist \l__blub_int
\int_incr:N \l__blub_int
}
\renewcommand\thepage{%
\clist_item:Nn \l__quack_clist {\fp_eval:n {randint(\clist_count:N\l__quack_clist)}}
}
\ExplSyntaxOff
\begin{document}
\tableofcontents
\chapter{Intro}
\section{Zzzz}aaaa
\section{Zzzzz}aaaa \clearpage bbbb
\section{Zzzzz}aaaa
\chapter{Something}
\section{Zzzz zzz}aaaa
\section{Zzzzzz zzz}aaaa \clearpage bbbb
\section{Zzzzzzz zzz}aaaa
\end{document}