41

I would like a command \egreg which produces “egreg”. However, there is no reason to limit yourself to one “reg”. Who knows, maybe one day you just feel like writing “egregregregreg" for some reason. So the command should also take an optional argument, specifying the number of “reg”’s you want.

I know there are easy solutions involving loops, but given that it’s April 1, the most ridiculous solution will be accepted.

\documentclass{article}

\NewDocumentCommand\egreg{o}{%
    % something
}

\begin{document}

\egreg % should produce "egreg"
\egreg[0] % should produce "eg"
\egreg[1] % should produce "egreg"
\egreg[2] % should produce "egregreg"
\egreg[5] % should produce "egregregregregreg"

Perhaps we might also want to allow negative values:

\egreg[-1] % should produce "regeg"
\egreg[-2] % should produce "regregeg"

Maybe also complex values?

\egreg[i] % perhaps "$\text{eg} + i\text{reg}$"?

Perhaps someone can also figure out
what to do with quaternionic values?

\end{document}

7
  • 12
    Great April 1st post! I'm sure egreg will answer :D
    – CarLaTeX
    Commented Apr 1, 2023 at 7:59
  • 9
    I first thought that this was about a macro that outputs marvellous solutions to (or even just magically solve on-the-fly) tricky TeX problems whenever being used in your code ... Commented Apr 1, 2023 at 8:02
  • 4
    @JasperHabicht I promise that if you can come up with a command that can do that consistently, your answer will also be accepted and appropriately awarded. But \newcommand\egreg[1]{Ask ChatGPT about #1} doesn’t count. 😆
    – Gaussler
    Commented Apr 1, 2023 at 8:04
  • 4
    I think, on April 1st, the macro should output variations of the string april instead of egreg ... Commented Apr 1, 2023 at 10:51
  • 17
    How very egregious.
    – JonathanZ
    Commented Apr 1, 2023 at 18:17

9 Answers 9

34
+500

I think the image-inary part should be drawn with TikZlings:

\documentclass{article}
\usepackage{xstring}
\usepackage{etoolbox}
\usepackage{tikzlings}
\newcommand{\egregnum}[1]{%
  \begin{tikzpicture}[
    every node/.style={inner sep=0pt}, 
    baseline=(a0.base)
    ]
    \node (a0) {eg};
    \ifnumgreater{#1}{0}{%
    \foreach \x [count=\prev from 0] in {1,...,#1}
        \node[anchor=west] (a\x) at (a\prev.east){reg};
        }{%
    \ifnumless{#1}{0}{%
        \foreach \x [evaluate=\x as \numpos using int(\x * -1),
                    evaluate=\x as \prev using int((\x * -1)-1)] 
                    in {-1,...,#1}                  
                \node[anchor=east] (a\numpos) at (a\prev.west){reg};            
            }{}%
        }%
    \end{tikzpicture}
    }

\newcommand{\egregimm}{%
           \raisebox{-.3cm}{\begin{tikzpicture}
                \tikzling[
        scale=0.5,signpost={reg}
        ]
            \end{tikzpicture}
            }}
    
\newcommand{\egreg}[1][1]{%
    \IfDecimal{#1}{%
        \egregnum{#1}%
        }{%
        \StrDel{#1}{ }[\complesso]%
        \StrSubstitute{\complesso}{-}{+}[\contasegni]%
        \StrCount{\contasegni}{+}[\numsegni]%
        \StrPosition[\numsegni]{\contasegni}{+}[\signposition]%
        \StrChar{\complesso}{\signposition}[\segno]%
        \IfStrEq{\segno}{-}{%immaginario negativo
            \StrBehind[\numsegni]{#1}{-}[\partei]%
            \StrSubstitute{\partei}{ }{}[\parteimm]%
            \StrSubstitute{\parteimm}{i}{}[\immaginario]%
            \IfDecimal{\immaginario}{%
                \foreach \cifreimm in {1,...,\immaginario}{\egregimm}
                }{%
                \egregimm
                }%
            \StrBefore[\numsegni]{\complesso}{-}[\reale]%
            \IfDecimal{\reale}{%
                \egregnum{\reale}
                }{%
                \egregnum{0}
                }%
        }{% immaginario positivo
            \StrBefore{\complesso}{+}[\reale]%
            \IfDecimal{\reale}{%
                \egregnum{\reale}
                }{%
                \egregnum{0}
                }%
            \StrBehind{#1}{+}[\partei]%
            \StrSubstitute{\partei}{ }{}[\parteimm]%
            \StrSubstitute{\parteimm}{i}{}[\immaginario]%
            \IfDecimal{\immaginario}{%
                \foreach \cifreimm in {1,...,\immaginario}{\egregimm}
                }{%
                \egregimm
                }%
        }%
    }
}

\begin{document}
    \verb|\egreg|: \egreg % should produce "egreg"
    
    \verb|\egreg[0]|: \egreg[0] % should produce "eg"
    
    \verb|\egreg[1]|: \egreg[1] % should produce "egreg"
    
    \verb|\egreg[2]|: \egreg[2] % should produce "egregreg"
    
    \verb|\egreg[5]|: \egreg[5] % should produce "egregregregregreg"
    
    \verb|\egreg[-1]|: \egreg[-1] % should produce "regeg"
    
    \verb|\egreg[-2]|: \egreg[-2] % should produce "regregeg"
    
    \verb|\egreg[i]|: \egreg[i] % perhaps "$\text{eg} + i\text{reg}$"?

        \verb|\egreg[3+2i]|: \egreg[3+2i] 

        \verb|\egreg[2 + 3i]|: \egreg[2 + 3i]

        \verb|\egreg[-2 + 4i]|: \egreg[-2 + 4i]

        \verb|\egreg[1 - 2i]|: \egreg[1 - 2i]

        \verb|\egreg[-2 - i]|: \egreg[-2 - i]
 
        \verb|\egreg[-i]|: \egreg[-i]

\end{document}

enter image description here

10
  • 8
    Can I hug it? 😍
    – Gaussler
    Commented Apr 2, 2023 at 7:12
  • 8
    @Gaussler Of course, you can! And they will be very happy of it!
    – CarLaTeX
    Commented Apr 2, 2023 at 7:14
  • 2
    The TikZlings won the competition for you. Congratulations!
    – Gaussler
    Commented Apr 3, 2023 at 11:23
  • 2
    @Gaussler I'm very proud if it! Thanks!
    – CarLaTeX
    Commented Apr 3, 2023 at 11:28
  • 5
    More confirmation of the TeX.se adage "If you want more rep, add a picture". :)
    – Alan Munn
    Commented Apr 3, 2023 at 13:23
20

Out of competition, of course. The most ridiculous answers will be rewarded with bounty points.

Since you don't want expandability, as witnessed by the proposed syntax, here's my version. Note how most endlines are not masked with % and the abundance of unneeded spaces.

\documentclass{article}

\NewDocumentCommand{\egreg}{o}{%
  \IfNoValueTF{#1}{\printegreg{1}}{\printegreg{#1}}%
 }

\NewDocumentCommand{\printegreg}{m}{%
  $
  \begingroup\uccode`~ = `m \uppercase{\endgroup\def~}{\hbox{reg}}
  \mathcode`m = "8000
  \ifnum#1<0 \romannumeral-\number\number#1 000 \fi
  \hbox{eg}
  \ifnum#1>0 \romannumeral\number\number#1 000 \fi
  $%
}

\newcounter{egreg}
\newcount\plainegreg

\begin{document}

\egreg \  should produce ``egreg''

\egreg[0] should produce ``eg''

\egreg[1] should produce ``egreg''

\egreg[2] should produce ``egregreg''

\egreg[5] should produce ``egregregregregreg''

\egreg[-1] should produce ``regeg''

\egreg[-2] should produce ``regregeg''

\setcounter{egreg}{4}

\egreg[\value{egreg}]

\plainegreg=-3

\egreg[\plainegreg]

\end{document}

enter image description here

13
  • 17
    @Mico I'm real, not imaginary.
    – egreg
    Commented Apr 1, 2023 at 8:51
  • 8
    Well, we all have our complexities, don’t we?
    – Gaussler
    Commented Apr 1, 2023 at 8:52
  • 10
    If I offended you with this competition, I deeply “regreg” it. 😀
    – Gaussler
    Commented Apr 1, 2023 at 9:47
  • 9
    @Gaussler Not in the least! I'll award bounties to the most ridiculous answers.
    – egreg
    Commented Apr 1, 2023 at 9:48
  • 11
    @Gaussler That's an egregious pun! :-)
    – gusbrs
    Commented Apr 1, 2023 at 12:58
18
+500

I think the best way to thank egreg for all the help was to solve this exercise using a code roughly as readable as most LaTeX code I can read on this forum (in particular yours egreg, but it's not your fault if LaTeX is not really readable :-P)… but a bit prettified (I took the liberty to modify the minus version to actually be a true inverse, i.e. equal when reading backward).

\documentclass[a4paper]{article}
\usepackage{bxbluf} % See below, from https://gist.github.com/zr-tex8r/7527995

\procbf{\egregBF}{
         +>,-----           --------         
       ------------       ------------       
      --------[<[-]>     ++++++++++++++      
     ++++++++++++++++   +++++++++++++++[     
    >[>++++++++++<-]>   [-<+>]<<---------    
    ------------------ ------------------    
   ---[>+<-],]++++++++ +++++++++++++++++++   
   +++++++++++++++++++++++++++++++++++++++   
   +++++++++++++++++++++++++++++++++++.++.   
  [-]>[->++++++++++++++++++++++++++++++++++  
  +++++++++++++++++++++++++++++++++++++++++  
  +++++++++++++++++++++++++++++++++++++++.-  
    ------------.++.[-]<],[--------------    
     -------------------------------]]<[     
      [-]>,[>[>++++++++++<-]>[-<+>]<<--      
       -------------------------------       
        ---------------[>+<-],]>[->++        
        +++++++++++++++++++++++++++++        
         +++++++++++++++++++++++++++         
          +++++++++++++++++++++++++          
           ++++++++++++++++++++.--           
            .+++++++++++++.[-]<]+            
             +++++++++++++++++++             
              +++++++++++++++++              
               +++++++++++++++               
               +++++++++++++++               
                +++++++++++++                
                 +++++++++++                 
                  +++++++++                  
                   +++.--.                   
                    [-]]♥                    
                     ♥♥♥                     
                      ♥                      
                      ♥         
}


\NewDocumentCommand{\egreg}{O{1}}{\egregBF{#1}}
\begin{document}
\begin{itemize}
\item \texttt{\textbackslash egreg}: \egreg
\item \texttt{\textbackslash egreg[12]}: \egreg[12]
\item \texttt{\textbackslash egreg[-2]}: \egreg[-2]
\end{itemize}

\end{document}

enter image description here

Note that you need to create also a bxbluf.sty file to interpret the Brainfuck in the above code (from https://gist.github.com/zr-tex8r/7527995, slighty improved to remove unwanted space):

% bxbluf.sty

%% package declaration
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{bxbluf}[2013/11/11 v0.2]

%% preparations
\def\bxbf@pkgname{bxbluf}
\def\bxbf@error{\PackageError\bxbf@pkgname}
\def\bxbf@warn{\PackageWarningNoLine\bxbf@pkgname}
\def\bxbf@err@umbgr{%
  \bxbf@error{Unmatched [ found}\@ehc
}
\def\bxbf@err@umegr{%
  \bxbf@error{Unmatched ] found}\@ehc
}
\def\bxbf@warn@hichr{%
  \bxbf@warn{Non 8-bit character found}%
}
\def\bxbf@warn@ineof{%
  \bxbf@warn{End-of-input reached}%
}
%
\newif\ifbxbf@inloop
\newif\ifbxbf@g@error
\newif\ifbxbf@optok
\providecommand*\bxDebug[1]{}

%--------------------------------------- base

%% variables
\newcount\bxbf@count
\let\bxbf@prcode\@empty

%% \bxbf@op@list : operator list
\def\bxbf@op@list{%
  \do\bxbf@AP\do\bxbf@AV\do\bxbf@ID\do\bxbf@OD\do\bxbf@LP
  \do\bxbf@RP\do\bxbf@RV\do\bxbf@AX\do\bxbf@RX\do\bxbf@SF
}

%% \bxbf@op@frozen
\let\bxbf@op@frozen\relax

%% \bxbf@op@noop
\def\bxbf@op@noop#1{}

%% \bxbf@switch@all@op\CS
\def\bxbf@switch@all@op#1{%
  \let\bxbf@tmpa#1%
  \let\do\bxbf@switch@all@op@do \bxbf@op@list
}
\def\bxbf@switch@all@op@do#1{%
  \let#1\bxbf@tmpa
}

%% \bxbf@modulo{<num>}
\def\bxbf@modulo#1{%
  \@tempcnta=#1\relax \bxbf@count\@tempcnta
  \divide\@tempcnta\bxbf@rbase \multiply\@tempcnta\bxbf@rbase
  \advance\bxbf@count-\@tempcnta
}

%% \bxbf@show
% for debug
\def\bxbf@show{%
  \bxbf@switch@all@op\bxbf@op@frozen
  \bxDebug{prog:\bxbf@prcode}%
}

%--------------------------------------- \scantokens emulation
\ifx\scantokens\@undefined
  % when \scantokens is unavailable
  \newwrite\bxbf@tempfile
  \def\bxbf@tempfilename{\[email protected]}

  \def\bxbf@scantokens#1{%
    \begingroup
      \toks@={#1}%
      \immediate\openout\bxbf@tempfile=\bxbf@tempfilename\relax
      \immediate\write\bxbf@tempfile{\the\toks@}%
      \immediate\closeout\bxbf@tempfile
    \endgroup
    \input{\bxbf@tempfilename}%
  }%

\else
  % uses \scantokens if available
  \let\bxbf@scantokens\scantokens
\fi
%--------------------------------------- LaTeX interface

%% variables
\newcount\bxbf@proc@maxid
\let\bxbf@decl@mode\relax
\let\bxbf@out@verbatim\relax
\let\bxbf@eofval=*

%%<*> \execbf[*] / \execbfwithinput[*] / \procbf[*]
\DeclareRobustCommand*\execbf{%
  \@ifstar{\bxbf@procbf{n}{1}}{\bxbf@procbf{n}{0}}%
}
\DeclareRobustCommand*\execbfwithinput{%
  \@ifstar{\bxbf@procbf{i}{1}}{\bxbf@procbf{i}{0}}%
}
\DeclareRobustCommand*\procbf{%
  \@ifstar{\bxbf@procbf{p}{1}}{\bxbf@procbf{p}{0}}%
}
\def\bxbf@procbf#1#2{%
  \let\bxbf@decl@mode=#1\relax
  \chardef\bxbf@out@verbatim=#2\relax
  \def\bxbf@proc@id{0}%
  \if i\bxbf@decl@mode
    \let\bxbf@tmpa\bxbf@procbf@winput
  \else\if p\bxbf@decl@mode
    \advance\bxbf@proc@maxid\@ne
    \edef\bxbf@proc@id{\the\bxbf@proc@maxid}%
    \let\bxbf@tmpa\bxbf@procbf@wproc
  \else
    \let\bxbf@input\@empty
    \let\bxbf@tmpa\bxbf@procbf@a
  \fi\fi
  \bxbf@tmpa
}
\def\bxbf@procbf@winput#1{% <input>
  \def\bxbf@input{#1}%
  \bxbf@procbf@a
}
\def\bxbf@procbf@wproc#1{% \ProcCS
  \def\bxbf@proc@cs{\noexpand#1}%
  \bxbf@procbf@a
}
\def\bxbf@procbf@a#1{% <program>
  \begingroup
    \global\expandafter\chardef\csname bxbf@OutVerb/\bxbf@proc@id\endcsname
     =\bxbf@out@verbatim
    \bxbf@parse{#1}%
    \bxbf@optimize
    \global\expandafter\let\csname bxbf@PrArray/\bxbf@proc@id\endcsname
     =\bxbf@prcode
  \endgroup
  \ifnum\bxbf@proc@id>0
    \edef\bxbf@tmpa{%
      \gdef\bxbf@proc@cs{\noexpand\bxbf@invoke@proc{\bxbf@proc@id}}%
    }%
    \bxbf@tmpa
  \else % immediate execution
    \bxbf@invoke@proc{\bxbf@proc@id}{\bxbf@input}%
  \fi
}

%% \bxbf@invoke@proc{<id>}{<input>}
\def\bxbf@invoke@proc#1#2{%
  \begingroup
    \bxbf@stringify\bxbf@input{#2}%
    \expandafter\let\expandafter\bxbf@prcode
     \csname bxbf@PrArray/#1\endcsname
    \bxbf@execute
    \xdef\bxbf@g@tmpa{\noexpand\bxbf@process@str
      {\csname bxbf@OutVerb/#1\endcsname}{\bxbf@output}}%
  \endgroup
  \bxbf@g@tmpa
}
\def\bxbf@process@str#1#2{%
  \ifnum#1>\z@
    \begingroup
      \let\bxbfLF\newline \let\bxbfSP\ %
      #2\relax
    \endgroup
  \else
    \begingroup
      \def\bxbfLF{^^J}\def\bxbfSP{ }%
      \xdef\bxbf@g@tmpa{\noexpand\bxbf@scantokens{#2}}%
    \endgroup
    \bxbf@g@tmpa
  \fi
}

%% \bxbf@stringify\CS{<text>}
\def\bxbf@stringify#1#2{%
  \edef\bxbf@tmpa{#2}%
  \expandafter\bxbf@stringify@a\meaning\bxbf@tmpa\bxbf@end#1%
}
\def\bxbf@stringify@a#1->#2\bxbf@end#3{%
  \def#3{#2}%
}

%%<*> \bfeofvalue{<val>}
\newcommand*\bfeofvalue[1]{%
  \def\bxbf@tmpa{#1}%
  \ifx\bxbf@tmpa\bxbf@@star \let\bxbf@eofval=*\relax
  \else\ifx\bxbf@tmpa\bxbf@@bang \let\bxbf@eofval=!\relax
  \else \afterassignment\bxbf@eofvalue@a\bxbf@count=\bxbf@tmpa\bxbf@tn
  \fi\fi
}
\def\bxbf@eofvalue@a#1\bxbf@tn{%
  \def\bxbf@tmpa{#1}%
  \ifx\bxbf@tmpa\@empty
    \bxbf@modulo\bxbf@count
    \ifnum\bxbf@count<\z@ \advance\bxbf@count\bxbf@rbase \fi
    \chardef\bxbf@eofval\bxbf@count
  \else \bxbf@count=\bxbf@tn
  \fi
}
\let\bxbf@tn\relax
\def\bxbf@@star{*}
\def\bxbf@@bang{!}

%--------------------------------------- parse

%% variables
\let\bxbf@block\@empty
\let\bxbf@prev@op\@empty
\let\bxbf@source@rest\@empty
\mathchardef\bxbf@rbase=256
\mathchardef\bxbf@mcmax="7FFF

%% \bxbf@chk
\def\bxbf@chk{\space}

%% \bxbf@parse
\long\def\bxbf@parse#1{%
  \bxbf@switch@all@op\bxbf@op@frozen
  \bxbf@inloopfalse
  \global\bxbf@g@errorfalse
  \edef\bxbf@tmpa{%
    \noexpand\bxbf@parse@block{#1\noexpand\bxbf@chk}}%
  \bxbf@tmpa
  \ifbxbf@g@error \let\bxbf@prcode\@empty
  \else \let\bxbf@prcode\bxbf@block
  \fi
}

%% \bxbf@parse@block
\long\def\bxbf@parse@block#1{%
  \let\bxbf@prev@op\@empty \bxbf@count\z@
  \let\bxbf@block\@empty
  \bxbf@parse@loop@a#1\bxbf@end
}

%% \bxbf@parse@loop
\def\bxbf@parse@loop{%
  \futurelet\bxbf@tmpa\bxbf@parse@loop@a
}
\def\bxbf@parse@loop@a{%
  \ifx\bxbf@tmpa\bgroup \expandafter\bxbf@parse@loop@b
  \else \expandafter\bxbf@parse@loop@ab
  \fi
}
\def\bxbf@parse@loop@ab{%
  \ifx\bxbf@tmpa\@sptoken \expandafter\bxbf@parse@loop@ac
  \else \expandafter\bxbf@parse@loop@c
  \fi
}
\expandafter\def\expandafter\bxbf@parse@loop@ac\space{%
  \bxbf@parse@loop
}
\long\def\bxbf@parse@loop@b#1{%
  \bxbf@parse@loop#1%
}
\long\def\bxbf@parse@loop@c#1{%
  \csname bxbf@p@h/\string#1\endcsname
  \bxbf@parse@loop
}
%% \bxbf@aprse@flush
\def\bxbf@parse@flush{%
  \ifnum\bxbf@count=\z@\else
    \edef\bxbf@block{\bxbf@block\bxbf@prev@op{\the\bxbf@count}}%
  \fi
}
%% \bxbf@aprse@nonaccum
\def\bxbf@parse@nonaccum#1{%
  \bxbf@parse@flush
  \def\bxbf@prev@op{#1}\bxbf@count\@ne
}
%% \bxbf@aprse@accum
\def\bxbf@parse@accum#1#2{%
  \def\bxbf@tmpa{#1}%
  \ifx\bxbf@prev@op\bxbf@tmpa
    \advance\bxbf@count#2%
  \else
    \bxbf@parse@flush
    \bxbf@count#2\def\bxbf@prev@op{#1}
  \fi
}
%% \bxbf@aprse@new@block
\long\def\bxbf@parse@new@block#1#2\bxbf@end{% #1 gobbled
  \bxbf@parse@flush
%\bxDebug{new:\bxbf@block}%
  \begingroup
    \bxbf@inlooptrue
    \bxbf@parse@block{#2}%
    \global\let\bxbf@g@tmpa\bxbf@block
    \global\let\bxbf@g@tmpb\bxbf@source@rest
  \endgroup
  \let\bxbf@source@rest\bxbf@g@tmpb
  \edef\bxbf@block{\bxbf@block\bxbf@LP{\bxbf@g@tmpa}}%
%\bxDebug{back:\bxbf@block}%
  \let\bxbf@prev@op\@empty \bxbf@count\z@
  \expandafter\bxbf@parse@loop\bxbf@source@rest\bxbf@end
}
%% \bxbf@aprse@end@block
\long\def\bxbf@parse@end@block#1#2\bxbf@end{% #1 gobbled
  \bxbf@parse@flush
  \ifbxbf@inloop
    \def\bxbf@source@rest{#2}%
  \else
    \bxbf@err@umegr
    \global\bxbf@g@errortrue
    \let\bxbf@source@rest\@empty
  \fi
}
%% \bxbf@aprse@finale
\long\def\bxbf@parse@finale#1#2\bxbf@end{% #1 gobbled
  \bxbf@parse@flush
  \ifbxbf@inloop
    \bxbf@err@umbgr
    \global\bxbf@g@errortrue
    \def\bxbf@source@rest{\bxbf@chk}%
  \fi
}

%% \bxbf@decl@handler{<token>}{<body>}
\def\bxbf@decl@handler#1{%
  \expandafter\def\csname bxbf@p@h/#1\endcsname
}
\bxbf@decl@handler{+}{\bxbf@parse@accum\bxbf@AV\@ne}
\bxbf@decl@handler{-}{\bxbf@parse@accum\bxbf@AV\m@ne}
\bxbf@decl@handler{>}{\bxbf@parse@accum\bxbf@AP\@ne}
\bxbf@decl@handler{<}{\bxbf@parse@accum\bxbf@AP\m@ne}
\bxbf@decl@handler{,}{\bxbf@parse@nonaccum\bxbf@ID}
\bxbf@decl@handler{.}{\bxbf@parse@nonaccum\bxbf@OD}
\bxbf@decl@handler{[}{\bxbf@parse@new@block}
\bxbf@decl@handler{]}{\bxbf@parse@end@block}
\bxbf@decl@handler{\string\bxbf@chk}{\bxbf@parse@finale}

%--------------------------------------- optimize

%% variables
\let\bxbf@g@block\@empty

%% \bxbf@g@addto@block
\def\bxbf@g@addto@block{\g@addto@macro\bxbf@g@block}

%% \bxbf@opt@addop
\def\bxbf@opt@addop#1#2{%
  \bxbf@g@addto@block{#1#2}%
}

%% \bxbf@intern{<num>}\cont
\edef\bxbf@H{\expandafter\@gobble\string\#}
\def\bxbf@intern#1{%
  \expandafter\bxbf@intern@a\csname\bxbf@H\number#1%
   \expandafter\endcsname\number#1\relax
}
\def\bxbf@intern@a#1#2\relax#3{%
  \ifx#1\relax
    \ifnum#2>\bxbf@mcmax \gdef#1{#2 }%
    \else \global\mathchardef#1=#2\relax
    \fi
  \fi
  #3#1%
}

%% \bxbf@intern@red{<num>}\cont
\def\bxbf@intern@red#1{%
  \bxbf@modulo{#1}%
  \bxbf@intern\bxbf@count
}

%% \bxbf@optimize
\def\bxbf@optimize{%
  \bxbf@switch@opt
  \global\let\bxbf@g@block\@empty
  \bxbf@prcode
  \let\bxbf@prcode\bxbf@g@block
}

%% \bxbf@switch@opt
\def\bxbf@switch@opt{%
  \let\bxbf@AP\bxbf@opt@AP\let\bxbf@AV\bxbf@opt@AV
  \let\bxbf@ID\bxbf@opt@ID\let\bxbf@OD\bxbf@opt@OD
  \let\bxbf@LP\bxbf@opt@LP
  \let\bxbf@RP\bxbf@op@error\let\bxbf@RV\bxbf@op@error
  \let\bxbf@AX\bxbf@opt@AX\let\bxbf@RX\bxbf@op@error
  \let\bxbf@SF\bxbf@op@error
}

%% \bxbf@opt@ID / \bxbf@opt@OD
\def\bxbf@tmpa#1{%
  \def\bxbf@opt@ID##1{\bxbf@g@addto@block{\bxbf@ID#1}}%
  \def\bxbf@opt@OD##1{\bxbf@g@addto@block{\bxbf@OD#1}}%
}
\bxbf@intern{1}\bxbf@tmpa

%% \bxbf@opt@AP
\def\bxbf@opt@AP#1{%
  \ifnum#1<\z@ \bxbf@intern{-#1}{\bxbf@opt@addop\bxbf@RP}%
  \else        \bxbf@intern{+#1}{\bxbf@opt@addop\bxbf@AP}%
  \fi
}
%% \bxbf@opt@AV
\def\bxbf@opt@AV#1{%
  \ifnum#1<\z@ \bxbf@intern@red{-#1}{\bxbf@opt@addop\bxbf@RV}%
  \else        \bxbf@intern@red{+#1}{\bxbf@opt@addop\bxbf@AV}%
  \fi
}
%% \bxbf@opt@AX
\def\bxbf@opt@AX#1{%
  \ifnum#1<\z@ \bxbf@intern@red{-#1}{\bxbf@opt@addop\bxbf@RX}%
  \else        \bxbf@intern@red{+#1}{\bxbf@opt@addop\bxbf@AX}%
  \fi
}

%% \bxbf@opt@check
\def\bxbf@opt@check#1{%
  \bxbf@optokfalse
  \begingroup
    \bxbf@switch@all@op\bxbf@opt@check@ng
    \let\bxbf@AV\bxbf@opt@check@AV
    \let\bxbf@AP\bxbf@opt@check@AP
    \bxbf@count\z@ \@tempcntb\z@
    #1\bxbf@opt@check@fin
  \endgroup
}
\def\bxbf@opt@check@ng#1\bxbf@opt@check@fin{}
\def\bxbf@opt@check@AP#1{%
  \advance\bxbf@count#1\relax
}
\def\bxbf@opt@check@AV#1{%
  \ifnum\bxbf@count=\z@
    \advance\@tempcntb#1\relax
  \fi
}

%% \bxbf@opt@check@fin
\def\bxbf@opt@check@fin{%
  \ifnum\bxbf@count=\z@ \ifnum\@tempcntb=\m@ne
    \aftergroup\bxbf@optoktrue
  \fi\fi
}

%% \bxbf@opt@LP
\def\bxbf@opt@LP#1{%
  \begingroup
    \bxbf@opt@check{#1}%
    \let\bxbf@save@block\bxbf@g@block
    \global\let\bxbf@g@block\@empty
    \ifbxbf@optok
      \let\bxbf@AV\bxbf@AX
    \fi
    #1%
    \expandafter\bxbf@opt@LP@a\expandafter{\bxbf@g@block}%
  \endgroup
}
\def\bxbf@opt@LP@a#1{%
  \let\bxbf@g@block\bxbf@save@block
  \ifbxbf@optok \g@addto@macro\bxbf@g@block{\bxbf@SF{#1}}%
  \else \g@addto@macro\bxbf@g@block{\bxbf@LP{#1}}%
  \fi
}

%% \bxbf@opt@add\CS{<arg>}
\def\bxbf@opt@add#1#2{%
  \g@addto@macro\bxbf@g@block{#1{#2}}%
}

%--------------------------------------- execute
\edef\bxbf@restorecc{\catcode127=\the\catcode127\relax}
\catcode127=12

%% variables
\newcount\bxbf@dptr
\let\bxbf@str@in\@empty
\let\bxbf@str@out\@empty
\chardef\bxbf@zero=0
\chardef\bxbf@lctr=0

%% \bxbf@execute
\def\bxbf@execute{%
%\bxbf@show
  \bxbf@switch@exec
  \global\let\bxbf@str@in\bxbf@input
  \global\let\bxbf@str@out\@empty
  \global\bxbf@g@errorfalse
  \bxbf@dptr\z@
  \bxbf@prcode\bxbf@exec@fin
  \ifbxbf@g@error \let\bxbf@output\@empty
  \else \let\bxbf@output\bxbf@str@out
  \fi
}
\let\bxbf@exec@fin\relax

%% \bxbf@exec@halt
% NB. This is not counted as error.
\def\bxbf@exec@halt#1\bxbf@exec@fin{}

%% \bxbf@swtich@exec
\def\bxbf@switch@exec{%
  \let\bxbf@AP\bxbf@exec@AP\let\bxbf@AV\bxbf@exec@AV
  \let\bxbf@ID\bxbf@exec@ID\let\bxbf@OD\bxbf@exec@OD
  \let\bxbf@LP\bxbf@exec@LP
  \let\bxbf@RP\bxbf@exec@RP\let\bxbf@RV\bxbf@exec@RV
  \let\bxbf@AX\bxbf@exec@AX\let\bxbf@RX\bxbf@exec@RX
  \let\bxbf@SF\bxbf@exec@SF
}

%% bxbf@exec@AP
\def\bxbf@exec@AP#1{%
  \advance\bxbf@dptr#1%
%\bxDebug{AP:\number#1;\number\bxbf@dptr}%
}
%% bxbf@exec@RP
\def\bxbf@exec@RP#1{%
  \advance\bxbf@dptr-#1%
%\bxDebug{RP:\number#1;\number\bxbf@dptr}%
}

%% bxbf@exec@AV
\def\bxbf@exec@AV{%
  \expandafter\bxbf@exec@AV@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@AV@a#1#2{%
  \ifx#1\relax \chardef#1#2%
  \else
    \bxbf@count#1\advance\bxbf@count#2%
    \ifnum\bxbf@count<\bxbf@rbase\else \advance\bxbf@count-\bxbf@rbase \fi
    \chardef#1\bxbf@count
  \fi
%\bxDebug{AV:#1:\the#2;\the#1}%
}
%% bxbf@exec@RV
\def\bxbf@exec@RV{%
  \expandafter\bxbf@exec@RV@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@RV@a#1#2{%
  \ifx#1\relax \chardef#1\bxbf@zero \fi
  \bxbf@count#1\advance\bxbf@count-#2%
  \ifnum\bxbf@count<\z@ \advance\bxbf@count\bxbf@rbase \fi
  \chardef#1\bxbf@count
%\bxDebug{RV:#1:\the#2;\the#1}%
}

%% bxbf@exec@ID
\def\bxbf@exec@ID{%
  \expandafter\bxbf@exec@ID@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@ID@a#1#2{%
  \ifx#1\relax \chardef#1\bxbf@zero \fi
  \bxbf@count#1%
  \bxbf@get@char
  \ifnum\bxbf@count<\z@ \expandafter\bxbf@exec@halt \fi
  \chardef#1\bxbf@count
%\bxDebug{ID:#1;\the#1}%
}

%% bxbf@exec@OD
\def\bxbf@exec@OD{%
  \expandafter\bxbf@exec@OD@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@OD@a#1#2{%
  \ifx#1\relax \chardef#1\bxbf@zero\fi%
  \bxbf@count#1%
  \bxbf@put@char%
%\bxDebug{OD:#1;\the#1}%
}

%% bxbf@exec@OD
\def\bxbf@exec@LP{%
  \expandafter\bxbf@exec@LP@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@LP@a#1{%
  \ifx#1\relax \chardef#1\bxbf@zero\fi%
%\bxDebug{LP:#1;\the#1}%
  \ifnum#1=\z@ \expandafter\@gobble%
  \else\expandafter\bxbf@exec@LP@b%
  \fi%
}
\def\bxbf@exec@LP@b#1{%
  #1\bxbf@exec@LP{#1}%
}

%% bxbf@exec@SF
\def\bxbf@exec@SF{%
  \expandafter\bxbf@exec@SF@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@SF@a#1#2{%
  \ifx#1\relax \chardef#1\bxbf@zero\fi%
  \chardef\bxbf@lctr#1%
  #2%
}

%% bxbf@exec@AX
\def\bxbf@exec@AX{%
  \expandafter\bxbf@exec@AX@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@AX@a#1#2{%
  \ifx#1\relax \chardef#1\bxbf@zero\fi
  \bxbf@count#2\multiply\bxbf@count\bxbf@lctr\advance\bxbf@count#1%
  \ifnum\bxbf@count<\bxbf@rbase\else\bxbf@modulo\bxbf@count\fi%
  \chardef#1\bxbf@count%
%\bxDebug{AX:#1:\the#2;\the#1}%
}
%% bxbf@exec@RX
\def\bxbf@exec@RX{%
  \expandafter\bxbf@exec@RX@a\csname ^^?\the\bxbf@dptr\endcsname}
\def\bxbf@exec@RX@a#1#2{%
  \ifx#1\relax%
    \chardef#1\bxbf@zero\fi%
  \bxbf@count#2\multiply\bxbf@count-\bxbf@lctr\advance\bxbf@count#1%
  \ifnum\bxbf@count<\z@ \bxbf@modulo\bxbf@count\fi%
  \ifnum\bxbf@count<\z@ \advance\bxbf@count\bxbf@rbase\fi%
  \chardef#1\bxbf@count%
%\bxDebug{RX:#1:\the#2;\the#1}%
}

\bxbf@restorecc
%--------------------------------------- virtual I/O

%% variables
\chardef\bxbfLF=10
\chardef\bxbfSP=32

%% \bxbf@get@char
\def\bxbf@get@char{%
  \ifx\bxbf@str@in\@empty \bxbf@get@char@mt%
  \else%
    \expandafter\bxbf@get@char@a\bxbf@str@in\bxbf@end%
  \fi%
}
\def\bxbf@get@char@a{%
  % don't discard spaces!
  \futurelet\bxbf@tmpa\bxbf@get@char@b%
}
\def\bxbf@get@char@b{%
  \ifx\bxbf@tmpa\@sptoken%
    \expandafter\bxbf@get@char@d%
  \else%
    \expandafter\bxbf@get@char@c%
  \fi%
}
\def\bxbf@get@char@c#1#2\bxbf@end{%
  \bxbf@count`#1\relax \gdef\bxbf@str@in{#2}%
  \ifnum\bxbf@count>\@cclv%
    \expandafter\bxbf@invalid@char%
  \fi
}
\def\bxbf@get@char@d{%
  \afterassignment\bxbf@get@char@e \let\bxbf@tmpa=%
}
\def\bxbf@get@char@e#1\bxbf@end{%
  \bxbf@count\bxbfSP \gdef\bxbf@str@in{#1}%
}
\def\bxbf@invalid@char{%
  \bxbf@warn@hichr%
  \bxbf@count\z@% non 8-bit char is replaced by zero
}
\def\bxbf@get@char@mt{%
  \ifx!\bxbf@eofval%
    \bxbf@warn@ineof%
    \bxbf@count\m@ne%
  \else\ifx*\bxbf@eofval\else%
    \bxbf@count\bxbf@eofval%
  \fi\fi%
}

%% \bxbf@put@char
\def\bxbf@put@char{%
  \lccode`!=\bxbf@count%
  \lowercase{%
    \xdef\bxbf@str@out{\bxbf@str@out%
      \ifnum\bxbf@count=\bxbfLF \bxbfLF%
      \else\ifnum\bxbf@count=\bxbfSP \bxbfSP%
      \else !\fi\fi}%
  }%
%\bxDebug{OUT:\bxbf@str@out:\the\bxbf@count}%
}

%--------------------------------------- all done
\endinput
%% EOF
4
  • 1
    Excellent ridiculous solution! You are right about the minus sign, that is the logical behaviour, but I only realized that after the answers had started coming in, so we're stuck with the original question.
    – Gaussler
    Commented Apr 4, 2023 at 6:03
  • 7
    This is worth another bounty!
    – egreg
    Commented Apr 4, 2023 at 12:53
  • @egreg Ahah thanks, I'm happy to see that you like it, I would never have expected to ever receive a bounty from you ^^ (the fact that you have never asked a single question does not help! tex.stackexchange.com/users/4427/egreg?tab=questions)
    – tobiasBora
    Commented Apr 4, 2023 at 13:52
  • 1
    Yes, @egreg is usually the one who receives bounties. Still, I hope that some day, just for fun, he will ask some question in here.
    – Gaussler
    Commented Apr 4, 2023 at 16:01
17

What we can do in OpTeX:

\optdef\wipet[1]{\if i\the\opt ${\rm wi}+i{\rm pet}$%
   \else
      \tmpnum=\the\opt\relax
      \ifnum\tmpnum<0 \fornum 1..-\tmpnum \do{pet}\fi
      wi%
      \ifnum\tmpnum>0 \fornum 1..\tmpnum \do{pet}\fi
   \fi
}

\wipet\ should produce ``wipet''

\wipet[0]\ should produce ``wi''

\wipet[1]\ should produce ``wipet''

\wipet[2]\ should produce ``wipetpet''

\wipet[5]\ should produce ``wipetpetpetpetpet''

\wipet[-1]\ should produce ``petwi''

\wipet[-2]\ should produce ``petpetwi''

\wipet[i]\ perhaps "${\rm wi} + i{\rm pet}$"

\bye
6
  • 6
    So, wipet is a pet, and wipetpet is like wipet’s pet?
    – Gaussler
    Commented Apr 1, 2023 at 12:05
  • 4
    Looking forward to @DavidCarlisle making a solution with a command \carlisle such that \carlisle[2] produces “carlislisle” or something.
    – Gaussler
    Commented Apr 1, 2023 at 12:09
  • 4
    @Gaussler true artists can not be mechanically copied in that way. Commented Apr 3, 2023 at 20:28
  • 1
    @Gaussler I already contributed this this month, and you expect more? Commented Apr 4, 2023 at 9:40
  • 1
    @DavidCarlisle Expect? Of course not. But I’m sure egreg would be happy. 😉 (And good work by the way!)
    – Gaussler
    Commented Apr 4, 2023 at 9:44
15
+500

Just for comparison, here is a version in Metapost (with apologies for being so far from the brief, apart from the "ridiculous" bit).

enter image description here

Compile with lualatex. (Here be dragons...)

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
picture payload; 
payload = textext("$\vcenter{\hbox{egreg}}\;$");
payload := payload scaled (1/abs(lrcorner payload - llcorner payload));
vardef dragon(expr level, a, b, r) = 
    if level = 0:
        draw a--b withcolor 3/4;
        draw payload zscaled (b-a) shifted a;
    else:
        save p; pair p;
        p = 0.7071067811865476[a, b] rotatedabout(a, r); 
        
        dragon(level-1, a, p, +abs(r));
        dragon(level-1, p, b, -abs(r)); 
    fi
enddef;
beginfig(1);
        dragon(11, origin, 600 right, 45); 
endfig;
\end{mplibcode}
\end{document}
1
  • @egreg I hope a "thank you" comment is allowed. Or perhaps I should say "Grazie mille!"
    – Thruston
    Commented Apr 6, 2023 at 16:31
14

I like recursions:

\documentclass{article}

\NewDocumentCommand\egreg{O{1}}{%
  \ifnum #1>0 eg\reg{#1}\else\ifnum #1<0 \reg{-#1}\fi eg\fi
}
\newcommand*{\reg}[1]{%
  \ifnum #1>0 \-reg\reg{\numexpr #1-1\relax}\fi
}

\begin{document}

\raggedright

\egreg{}  should produce ``egreg"

\egreg[0] should produce ``eg"

\egreg[1] should produce ``egreg"

\egreg[2] should produce ``egregreg"

\egreg[5] should produce ``egregregregregreg"

\medskip
Perhaps we might also want to allow negative values:

\egreg[-1] should produce ``regeg"

\egreg[-2] should produce ``regregeg"

\medskip
And also with hyphenation: \egreg[100]

\end{document}

Yes, handling of complex values is missing.

3
  • 1
    Good, in case I want to write “egregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregregreg”.
    – Gaussler
    Commented Apr 1, 2023 at 12:03
  • In general, isn’t it safer to use '' (two apostrophes) instead of " (quotation mark), especially since babel has a tendency to make the latter active?
    – Gaussler
    Commented Apr 2, 2023 at 12:54
  • 1
    @Gaussler Generally it would be safer and better to use csquotes. But IMHO the question was not about safer and better solutions. ;-) (But honestly, I was simply too lazy to replace all the quotes.)
    – cabohah
    Commented Apr 3, 2023 at 6:48
10

The following, LuaLaTeX-based solution probably won't qualify as being completely ridiculous, since it doesn't actually employ any loop-type control structures; it is left as an exercise to the motivated reader to replace Lua's string.rep function with a suitable for, while, or repeat .. until loop. Also, to keep @egreg's blood pressure from spiking up, I use \mathrm instead of \text directives...

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}

\begin{luacode*}
function egreg ( n )
  if n=="" then
    tex.sprint ("egreg")
  elseif n=="i" then
    tex.sprint ( "\\ensuremath{\\mathrm{eg}+i\\mathrm{reg}}" )
  else
    n = tonumber ( n )
    if n<0 then
      tex.sprint (        string.rep ( "reg",-n) .. "eg" )
    else
      tex.sprint ( "e" .. string.rep ( "gre", n) .. "g" )
    end
  end
end
\end{luacode*}
%% LaTeX-side code:
\newcommand\egreg[1][]{\directlua{egreg("#1")}}

\begin{document}

\obeylines % just for this example
\egreg 
\egreg[0] 
\egreg[1] 
\egreg[5] 
\egreg[-1] 
\egreg[-2]
\egreg[i] 

\end{document}
4
  • 2
    What about mixed expressions like 3+2i? 😉
    – Gaussler
    Commented Apr 1, 2023 at 8:52
  • 1
    @Gaussler - Should \egreg[3+2i] evaluate to \egreg[3]+i\egreg[2]? Or maybe its complex conjugate? :-)
    – Mico
    Commented Apr 1, 2023 at 9:06
  • 2
    Probably. But your guess is as good as mine. 😆
    – Gaussler
    Commented Apr 1, 2023 at 9:29
  • 4
    @Gaussler - Upon reflection, I've decided to leave the job of creating a complex-valued \egreg macro as an extra-credit assignment to readers...
    – Mico
    Commented Apr 1, 2023 at 13:12
4
+500

An expl3 abstraction, to a certain approximation:

egreg

carlisle

Besides being ridiculous in coding, style, design, purpose, outcome, background colour, submission time, some imaginable items, and other things, what this shows is that: egreg is, simultaneously, equivalent to, and not equivalent to, carlisle. Mirabile dictu!

And utterly ridiculous!!

MWE

\documentclass{article}
\usepackage{xcolor}
\usepackage{fontspec}
\setmainfont{NotoSerif}
\pagecolor{blue!5}

\ExplSyntaxOn

\tl_new:c {c_texta_tl}
\tl_set:cn 
    {c_texta_tl}
    { ~ produces ~}


\tl_new:N \l_tmpc_tl





\tl_new:N \l_egreg_oarg_tl
\newcommand{\egregnodelength}{2}
\int_new:N \l_enl_loop_int



%------------------------------------------------------------------

\cs_new:Npn \setegreg:n #1 
{ 
\exp_args:Nc 
\NewDocumentCommand { #1 } { o } {

    \tl_if_novalue:nTF { ##1 }
        { 
            \int_set:Nn \l_tmpa_int { 0 }
            }
        {
            \tl_set:Nn \l_egreg_oarg_tl { ##1 }
            \tl_if_eq:NnTF \l_egreg_oarg_tl { i } { \int_set:Nn \l_tmpa_int { 9999 }    }
            {\tl_if_eq:NnTF \l_egreg_oarg_tl { zzz } { \int_set:Nn \l_tmpa_int { 9998 }     }
            {\tl_if_eq:NnTF \l_egreg_oarg_tl { egreg } { \int_set:Nn \l_tmpa_int { 9997 }   }
                { 
                    \int_set:Nn \l_tmpa_int { ##1 }
                }
            }}
            }
            
    \tl_set:Nn \l_tmpa_tl { #1 } %***********
%   \tl_show:N \l_tmpa_tl 

    \tl_if_exist:cF { g_ \l_tmpa_tl _head_tl }
        {%%%%%%%%%%%
            \tl_new:c { g_ \l_tmpa_tl _head_tl }
            }
    \tl_if_exist:cF { g_ \l_tmpa_tl _tail_tl }
        {
            \tl_new:c { g_ \l_tmpa_tl _tail_tl }
            }

    \seq_set_split:NnV  \l_tmpa_seq {  } { \l_tmpa_tl } 
%   \tl_show:N \l_tmpa_tl
%   \seq_show:N \l_tmpa_seq
    

    \tl_clear:N \l_tmpb_tl
    \int_set:Nn \l_enl_loop_int { 0 }
    \int_do_until:nNnn { \l_enl_loop_int } = { \egregnodelength } 
    {
    
    \seq_pop_left:NN
        \l_tmpa_seq
        \l_tmpc_tl 
    \tl_put_right:NV
        \l_tmpb_tl
        \l_tmpc_tl      
        
        \int_incr:N \l_enl_loop_int
    }

    \tl_gset_eq:cN { g_ \l_tmpa_tl _head_tl } \l_tmpb_tl 

    \tl_gset:cn 
        { g_ \l_tmpa_tl _tail_tl } 
        { \seq_use:Nnnn
            \l_tmpa_seq
            {}{}{}
         }



        \int_case:nnTF
            { \l_tmpa_int }
            {
                { 9999 } { 
                        \tl_use:c { g_ \l_tmpa_tl _head_tl }
                        $ + i $
                        \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                             }
                { 9998 } { 
                            \showegreg{#1}
                             }
                { 9997 } { 
        \textcolor{blue}{
        \texttt{
        \textbackslash
        #1[#1]
        }}
        \tl_use:N \c_texta_tl 
        ``carlisle''.
                             }
            }
            {}{ %%%%%%%%%%%%%%%%%%%
        \int_case:nnTF
            { \int_sign:n { \l_tmpa_int } }
            {
                { 0 } {
%                       \tl_use:c { g_ \l_tmpa_tl _head_tl }
%                       \tl_use:c { g_ \l_tmpa_tl _tail_tl }

                            \int_until_do:nNnn
                                { \l_tmpb_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpb_int
                                }
                                    \tl_use:c { g_ \l_tmpa_tl _head_tl }
                            \int_until_do:nNnn
                                { \l_tmpa_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpa_int
                                }
                                
                            \tl_if_novalue:nT { ##1 }
                                { 
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                }
                        }
                { -1 } {
                            \int_set:Nn \l_tmpb_int { \int_abs:n { \l_tmpa_int } }
                            \int_until_do:nNnn
                                { \l_tmpb_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpb_int
                                }
                                    \tl_use:c { g_ \l_tmpa_tl _head_tl }
                        }
                { 1 } {
                            \tl_use:c { g_ \l_tmpa_tl _head_tl }
                            \int_until_do:nNnn
                                { \l_tmpa_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpa_int
                                }
                        }
            }
            {}{}            

        } %%%%%%%%%%%%%%%%%%%
    } % end-NDC


}


%------------------------------------------------------------------

\NewDocumentCommand{\makeegreg} { m } {
\setegreg:n  { #1 }
}

%------------------------------------------------------------------

\NewDocumentCommand { \egregX } { o } {

    \tl_if_novalue:nTF { #1 }
        { 
            \int_set:Nn \l_tmpa_int { 0 }
            }
        {
            \tl_set:Nn \l_egreg_oarg_tl { #1 }
            \tl_if_eq:NnTF \l_egreg_oarg_tl { i } { \int_set:Nn \l_tmpa_int { 9999 }    }
            {\tl_if_eq:NnTF \l_egreg_oarg_tl { zzz } { \int_set:Nn \l_tmpa_int { 9998 }     }
            {\tl_if_eq:NnTF \l_egreg_oarg_tl { egreg } { \int_set:Nn \l_tmpa_int { 9997 }   }
                { 
                    \int_set:Nn \l_tmpa_int { #1 }
                }
            }}
            }
            
    \tl_set:Nn \l_tmpa_tl { egreg } %***********
%   \tl_show:N \l_tmpa_tl 

    \tl_if_exist:cF { g_ \l_tmpa_tl _head_tl }
        {%%%%%%%%%%%
            \tl_new:c { g_ \l_tmpa_tl _head_tl }
            }
    \tl_if_exist:cF { g_ \l_tmpa_tl _tail_tl }
        {
            \tl_new:c { g_ \l_tmpa_tl _tail_tl }
            }

    \seq_set_split:NnV  \l_tmpa_seq {  } { \l_tmpa_tl } 
%   \tl_show:N \l_tmpa_tl
%   \seq_show:N \l_tmpa_seq
    

    \tl_clear:N \l_tmpb_tl
    \int_set:Nn \l_enl_loop_int { 0 }
    \int_do_until:nNnn { \l_enl_loop_int } > { \egregnodelength } 
    {
    
    \seq_pop_left:NN
        \l_tmpa_seq
        \l_tmpc_tl 
    \tl_put_right:NV
        \l_tmpb_tl
        \l_tmpc_tl      
        
        \int_incr:N \l_enl_loop_int
    }


    \tl_gset_eq:cN { g_ \l_tmpa_tl _head_tl } \l_tmpb_tl 

    \tl_gset:cn 
        { g_ \l_tmpa_tl _tail_tl } 
        { \seq_use:Nnnn
            \l_tmpa_seq
            {}{}{}
         }



        \int_case:nnTF
            { \l_tmpa_int }
            {
                { 9999 } { 
                        \tl_use:c { g_ \l_tmpa_tl _head_tl }
                        $ + i $
                        \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                             }
                { 9998 } { 
                            \showegreg{egreg}
                             }
                { 9997 } { 
        \textcolor{blue}{
        \texttt{
        \textbackslash
        egreg[egreg]
        }}
        \tl_use:N \c_texta_tl 
        ``carlisle''.
                             }
            }
            {}{ %%%%%%%%%%%%%%%%%%%
        \int_case:nnTF
            { \int_sign:n { \l_tmpa_int } }
            {
                { 0 } {
%                       \tl_use:c { g_ \l_tmpa_tl _head_tl }
%                       \tl_use:c { g_ \l_tmpa_tl _tail_tl }

                            \int_until_do:nNnn
                                { \l_tmpb_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpb_int
                                }
                                    \tl_use:c { g_ \l_tmpa_tl _head_tl }
                            \int_until_do:nNnn
                                { \l_tmpa_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpa_int
                                }
                                
                            \tl_if_novalue:nT { #1 }
                                { 
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                }
                        }
                { -1 } {
                            \int_set:Nn \l_tmpb_int { \int_abs:n { \l_tmpa_int } }
                            \int_until_do:nNnn
                                { \l_tmpb_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpb_int
                                }
                                    \tl_use:c { g_ \l_tmpa_tl _head_tl }
                        }
                { 1 } {
                            \tl_use:c { g_ \l_tmpa_tl _head_tl }
                            \int_until_do:nNnn
                                { \l_tmpa_int }
                                =
                                { \c_zero_int }
                                {
                                    \tl_use:c { g_ \l_tmpa_tl _tail_tl }
                                    \int_decr:N \l_tmpa_int
                                }
                        }
            }
            {}{}            

        } %%%%%%%%%%%%%%%%%%%
    } % end-NDC


%------------------------------------------------------------------


\NewDocumentCommand { \showegreg } { m o } {

\tl_if_novalue:nTF { #2 }
{
\tl_set:Nn 
    \l_tmpa_tl
    {
        \textcolor{blue}{
        \texttt{
        \textbackslash
        #1
        }}
        \tl_use:N \c_texta_tl 
        ``\use:c {#1}''.
    }
}   
{
\tl_set:Nn 
    \l_tmpa_tl
    {
        \textcolor{blue}{
        \texttt{
        \textbackslash
        #1[#2]
        }}
        \tl_use:N \c_texta_tl 
        ``\use:c {#1}[#2]''.
    }
}   
\tl_use:N 
    \l_tmpa_tl
}



\NewDocumentCommand { \showegregall } { m } {

\tex_par:D
\showegreg{#1} ~

\tex_par:D
\showegreg{#1}[0]

\tex_par:D
\showegreg{#1}[1]

\tex_par:D
\showegreg{#1}[-1]

\tex_par:D
\showegreg{#1}[-5]

\tex_par:D
\showegreg{#1}[i]

\tex_par:D
\showegreg{#1}[zzz]

\tex_par:D
\showegreg{#1}[egreg]

\renewcommand{\egregnodelength}{3}
\tex_par:D
\showegreg{#1}[-5]


\renewcommand{\egregnodelength}{1}
\tex_par:D
\showegreg{#1}[-5]

\renewcommand{\egregnodelength}{2}
\tex_par:D
\showegreg{#1}[-5]

}





\ExplSyntaxOff




\begin{document}

\makeegreg{egreg}
\egreg
\showegregall{egreg}

\newpage
\makeegreg{carlisle}
\carlisle

\showegregall{carlisle}
%
%\showegreg{carlisle}[4]
%
%\showegreg{carlisle}[i]

\end{document}
2
  • Bounty in progress!
    – egreg
    Commented Sep 7, 2023 at 10:47
  • The submission time is not necessarily ridiculous. With the right definition, I’m sure that yesterday can be regarded as April i.
    – Gaussler
    Commented Sep 8, 2023 at 8:05
3

Nobody remember multido?

enter image description here

\documentclass[a5paper]{article}
\usepackage{xstring}
\usepackage{multido}
\usepackage{xcolor}
\usepackage{graphicx}
\parindent0pt\parskip0pt
\newcommand\egreg[1][1]{%
\IfInteger{#1}{%
\ifnum #1<0 \multido{}{#1}{\reflectbox{reg}}\reflectbox{eg}\else
\ifnum #1>0 
{\bfseries{eg}\multido{}{#1}{reg}}\par
\else  eg\par\fi\fi}{{eg\emph{reg}}\par}}
\centering
\begin{document}
\sffamily
\multido{}{9}{\egreg[i]}  
\egreg [-4] \egreg [4]
\egreg [-3] \egreg [3]
\egreg [-2] \egreg [2]
\egreg[-1] \egreg [1]
\egreg[0]
\huge \egreg 
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .