I got the following code from Random shuffle itemize.
How to label (something like \label{1}, \ref{1}) a specific randomList item to print the corresponding letter at the end of the document?
\documentclass{article}
\usepackage{etoolbox}
\usepackage{pgfkeys}
\usepackage{pgfmath}
% code for generating a random permutation
\newcounter{randomListLength}% current length of our random list
\newcounter{randomListPosition}% current list index
\newcounter{newRandomListElementPosition}% position to insert new element
% insert #1 into the next position of \newRandomList unless the position
% index \randomListPosition is equal to \newRandomListElementPosition in
% which case the \newRandomListElement is added first
\newcommand\randomlyInsertElement[1]{%
\stepcounter{randomListPosition}%
\ifnum\value{randomListPosition}=\value{newRandomListElementPosition}%
\listxadd\newRandomList{\newRandomListElement}%
\fi%
\listxadd\newRandomList{#1}%
}
% \randomlyInsertInList{list name}{new list length}{new element}
\newcommand\randomlyInsertInList[3]{%
\pgfmathparse{random(1,#2)}%
\setcounter{newRandomListElementPosition}{\pgfmathresult}%
\ifnum\value{newRandomListElementPosition}=#2\relax%
\listcsxadd{#1}{#3}%
\else%
\def\newRandomList{}% start with an empty list
\def\newRandomListElement{#3}% and the element that we need to add
\setcounter{randomListPosition}{0}% starting from position 0
\xdef\currentList{\csuse{#1}}
\forlistloop\randomlyInsertElement\currentList%
\csxdef{#1}{\newRandomList}%
\fi%
}
% define some pgfkeys to allow key-value arguments
\pgfkeys{/randomList/.is family, /randomList,
environment/.code = {\global\letcs\beginRandomListEnvironment{#1}
\global\letcs\endRandomListEnvironment{end#1}
},
enumerate/.style = {environment=enumerate},
itemize/.style = {environment=itemize},
description/.style = {environment=description},
seed/.code = {\pgfmathsetseed{#1}}
}
\pgfkeys{/randomList, enumerate}% enumerate is the default
% finally, the code to construct the randomly permuted list
\makeatletter
\newcounter{randomListCounter}% for constructing \randomListItem@<k>'s
% \useRandomItem{k} prints item number k
\newcommand\useRandomItem[1]{\csname randomListItem@#1\endcsname}
% \setRandomItem{k} saves item number k for future use
% and builds a random permutation at the same time
\def\setRandomItem#1\par{\stepcounter{randomListCounter}%
\expandafter\protected@xdef\csname randomListItem@\therandomListCounter\endcsname{\noexpand\item#1}%
\randomlyInsertInList{randomlyOrderedList}{\therandomListCounter}{\therandomListCounter}%
}%
\let\realitem=\item
\makeatother
\newenvironment{randomList}[1][]{% optional argument -> pgfkeys
\pgfkeys{/randomList, #1}% process optional arguments
\setcounter{randomListLength}{0}% initialise length of random list
\def\randomlyOrderedList{}% initialise the random list of items
% Nthing is printed in the main environment. Instead, \item is
% used to slurp the "contents" of the item into randomListItem@<counter>
\let\item\setRandomItem%
}
{% now construct the list environment by looping over the randomly ordered list
\let\item\realitem
\setcounter{randomListCounter}{0}
\beginRandomListEnvironment\relax
\forlistloop\useRandomItem\randomlyOrderedList
\endRandomListEnvironment
}
% test compatibility with enumitem
\usepackage{enumitem}
\newlist{Testlist}{enumerate}{1} %
\setlist[Testlist]{label*=\alph*.}
\setlist{nosep}\parindent=0pt% for more compact output
\begin{document}
\begin{randomList}[environment=Testlist, seed=4]
\item First item
\item Second item
\item Third item
\end{randomList}
\end{document}