Expand an argument into a string

This does work via expansion so as shown works in \typeout as well as the typeset paragraph.



\documentclass{article}

\def\zz#1{\zzz#1(\relax)}
\def\zzz#1(#2){\zzA{#1}\ifx\relax#2\else(\zzA{#2})\expandafter\zzz\fi}
\def\zzA#1{\ifnum\numexpr0#1\relax>0 A\expandafter\zzA\expandafter{\the\numexpr#1-1\relax}\fi}

\begin{document}

\zz{3(2)2(1)}

\typeout{\zz{3(2)2(1)}}

\end{document}

puts

AAA(AA)AA(A)

on the terminal.


Here's an expandable approach using expl3. \Replicate[<tokens>]{<token list>} It will loop over your input <token list> looking for any sequence of digits and replacing them by that amount of repetitions of the input <tokens> (by default A). Everything else that is not a digit will be just forwarded to the output, so you can have things like

\Replicate{3(2)2(1)}
\Replicate[Z]{3(2)2(1)}
\Replicate[(Z)]{3(2)2(1)}
\Replicate[Z]{3 \textbf{(2) 2}( 1 )}
\edef\zzzzzzzzzzzz{\Replicate[Z]{3\textbf{(2)2}(1)}}
\texttt{\meaning\zzzzzzzzzzzz}

produce:

enter image description here


Here's the code:

\documentclass{article}
\usepackage{xparse}
\pagestyle{empty}
\ExplSyntaxOn
\NewExpandableDocumentCommand \Replicate { O{A} m }
  { \perror_replicate:nn {#1} {#2} }
\cs_new:Npn \perror_replicate:nn #1 #2
  {
    \__perror_replicate_loop:w #2
      \q_recursion_tail \q_recursion_stop {#1} { }
  }
\cs_new:Npn \__perror_replicate_loop:w #1 \q_recursion_stop
  {
    \tl_if_head_is_N_type:nTF {#1}
      { \__perror_replicate_parse_token:N }
      {
        \tl_if_head_is_group:nTF {#1}
          { \__perror_replicate_nested:n }
          { \__perror_replicate_output_space:w }
      }
    #1 \q_recursion_stop
  }
\use:nn { \cs_new:Npn \__perror_replicate_output_space:w } { ~ }
  { \__perror_replicate_output:nw { ~ } }
\cs_new:Npn \__perror_replicate_output:nw #1 #2 \q_recursion_stop #3 #4
  { \__perror_replicate_loop:w #2 \q_recursion_stop {#3} { #4 #1 } }
\cs_new:Npn \__perror_replicate_nested:n #1 #2 \q_recursion_stop #3
  {
    \exp_args:Ne \__perror_replicate_output:nw
      { { \perror_replicate:nn {#3} {#1} } }
    #2 \q_recursion_stop {#3}
  }
\cs_new:Npn \__perror_replicate_end:nn #1 #2 { \exp_not:n {#2} }
\cs_new:Npn \__perror_replicate_parse_token:N #1
  {
    \quark_if_recursion_tail_stop_do:Nn #1
      { \__perror_replicate_end:nn }
    \__perror_replicate_if_digit:NTF #1
      { \__perror_replicate_collect_number:nw }
      { \__perror_replicate_output:nw }
    {#1}
  }
\prg_new_conditional:Npnn \__perror_replicate_if_digit:N #1 { TF }
  {
    \if_int_compare:w 10 < 9 \token_to_str:N #1 \exp_stop_f:
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\cs_new:Npn \__perror_replicate_collect_number:nw #1 #2 \q_recursion_stop
  {
    \tl_if_head_is_N_type:nTF {#2}
      { \__perror_replicate_collect_number:nN }
      { \__perror_replicate_finish_number:nw }
    {#1} #2 \q_recursion_stop
  }
\cs_new:Npn \__perror_replicate_collect_number:nN #1 #2
  {
    \quark_if_recursion_tail_stop_do:Nn #2
      {
        \__perror_replicate_finish_number:nw {#1}
        \q_recursion_tail \q_recursion_stop
      }
    \__perror_replicate_if_digit:NTF #2
      { \__perror_replicate_collect_number:nw { #1 #2 } }
      { \__perror_replicate_finish_number:nw {#1} #2 }
  }
\cs_new:Npn \__perror_replicate_finish_number:nw #1 #2 \q_recursion_stop #3
  {
    \exp_args:Ne \__perror_replicate_output:nw
      { \prg_replicate:nn {#1} {#3} }
    #2 \q_recursion_stop {#3}
  }
\ExplSyntaxOff

\begin{document}
\Replicate{3(2)2(1)}

\Replicate[Z]{3(2)2(1)}

\Replicate[(Z)]{3(2)2(1)}

\Replicate[Z]{3 \textbf{(2) 2}( 1 )}

\edef\zzzzzzzzzzzz{\Replicate[Z]{3\textbf{(2)2}(1)}}

\texttt{\meaning\zzzzzzzzzzzz}

\end{document}

A piece of cake using LuaLaTeX (but yes, only works with LuaLaTeX):

\documentclass{standalone}
\usepackage{luacode}
\newcommand\myexpand[2]{%
\directlua{local function myexpand(x,s) return (x:gsub("(\csstring\%d+)", function(u) return s:rep(math.floor(u)) end)) end tex.sprint(myexpand(\luastring{#1},\luastring{#2}))}}
\begin{document}
\myexpand{(3)2(2)1}{A}
\end{document}

enter image description here