shuffle elements of a LaTeX3 sequence

I'd use Lua. It's much more readable.

\documentclass{article}
\usepackage{expl3}
\usepackage{luacode}

\begin{luacode*}
function shuffle(list)
   for i = #list,2,-1 do
      local j = math.random(i)
      list[i], list[j] = list[j], list[i]
   end
   tex.sprint(table.concat(list,","))
end
\end{luacode*}

\ExplSyntaxOn

\cs_generate_variant:Nn \seq_gset_from_clist:Nn { Nf }

\cs_new_protected:Npn \seq_shuffle_inplace:N #1
{
  \seq_gset_from_clist:Nf #1 { \lua_now_x:n { shuffle({ [[ \seq_use:Nn #1 { ]] , [[ } ]] }) } }
}

\seq_gset_from_clist:Nf \g_my_seq { 0,1,2,3,4,5,6,7,8,9 }

\seq_shuffle_inplace:N \g_my_seq

\begin{document}

\seq_use:Nnnn\g_my_seq{~and~}{,~}{,~and~}

\end{document}

Wooden version. No optimization. No “expert” writting this code.

\seq_new:N \l_alexg_origin_seq
\seq_new:N \l_alexg_destiny_seq
\int_new:N \l_alexg_random_int
\int_new:N \l_alexg_current_int
\cs_new_protected:Npn \seq_shuffle:N #1
 {
  \seq_set_eq:NN \l_alexg_origin_seq #1
  \seq_clear:N \l_alexg_destiny_seq
  \prg_replicate:nn { \seq_count:N #1 }
   {
    \int_set:Nn \l_alexg_random_int { \int_rand:nn { 1 } { \seq_count:N \l_alexg_origin_seq } }
    \int_zero:N \l_alexg_current_int
    \seq_clear:N \l_tmpa_seq
    \seq_map_inline:Nn \l_alexg_origin_seq
     {
      \int_incr:N \l_alexg_current_int
      \int_compare:nNnTF { \l_alexg_current_int } = { \l_alexg_random_int }
       { \seq_put_right:Nn \l_alexg_destiny_seq { ##1 } }
       { \seq_put_right:Nn \l_tmpa_seq { ##1 } }
     }
    \seq_set_eq:NN \l_alexg_origin_seq \l_tmpa_seq
   }
  \seq_set_eq:NN #1 \l_alexg_destiny_seq
 }

Complete expl3ification of @jfbu's answer.

\cs_new_protected:Npn \seq_shuffle_inplace:N #1
 {
  \int_zero:N \l_tmpa_int
  \seq_map_inline:Nn #1
   { 
    \int_incr:N \l_tmpa_int 
    \tl_set:cn { l_jfbu_shuffle_ \int_use:N \l_tmpa_int _tl } { ##1 } 
   }
  \int_step_inline:nnnn { \l_tmpa_int } { -1 } { 2 } 
   {
    \int_set:Nn \l_tmpb_int { \int_rand:nn { 1 } { ##1 } }
    \tl_set_eq:Nc \l_tmpa_tl { l_jfbu_shuffle_##1_tl }
    \tl_set_eq:cc { l_jfbu_shuffle_##1_tl } { l_jfbu_shuffle_ \int_use:N \l_tmpb_int _tl }
    \tl_set_eq:cN { l_jfbu_shuffle_ \int_use:N \l_tmpb_int _tl } \l_tmpa_tl
   }
 \tl_set:Nx #1 % more manual approach, ideally using \seq_set_from_clist:Nx
  {
   \s__seq
   \int_step_function:nnnN { 1 } { 1 } { \l_tmpa_int } \__jfbu_seq_construct:n
  }
 }
\cs_new:Npn \__jfbu_seq_construct:n #1
 { \exp_not:N \__seq_item:n { \exp_not:v { l_jfbu_shuffle_#1_tl } } }

I literally just added \seq_shuffle:N and \seq_gshuffle:N to expl3 (development version: https://github.com/latex3/latex3/). From what I can tell it's about 4 times faster than other solutions here except perhaps the LuaTeX one.

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\seq_gset_from_clist:Nn\g_my_seq{0,1,2,3,4,5,6,7,8,9}
\seq_gshuffle:N \g_my_seq
\begin{document}
\seq_use:Nnnn\g_my_seq{~and~}{,~}{,~and~}
\end{document}

Tags:

Expl3