I was looking at this question, Order table by row alphabeticaly, and thought, "that OP needs some sort of bubble sorter."
I had done a numerical bubble sorter here, Using LaTeX to compact a list of numbers (it actually sorted reference numbers and also compacted sequential references) and saw that I had also done an alpha-bubble sorter, as well here, Sorting a comma-separated list with LaTeX?.
Unfortunately, I discovered that the alpha-bubble sorter was prone to stack overflow from the recursion, when the list became larger. So I endeavored to streamline things here, rewriting the code. It is able to handle larger list sizes than the cited version, but as seen the included MWE, if I uncomment that one additional item in the list (encontrar
), I blow the stack.
Now I know that, in theory, the way to avoid blowing the stack during a conditional recursion is to ...\expandafter\recursion\fi
. However, I've never been good at mastering that technique when the recursion is nested deep in an \if
block, nor when the recursion is not a mere macro name, but instead a ...\recursion<data-block>\relax\fi
blob.
David C tells me that the stack size is set in texmf.cnf, and while I haven't yet found that file in my MikTeX installation, I realize that enlarging the stack is a poor fix in lieu of better code.
I also have not yet put in the \the\lccode
tweaks to overlook lettercase in the search, but one thing at a time.
I figure a general LaTeX alpha-bubble sorter would be a useful thing to more than just me, so I post it here as a question, in hopes that it can be beat into submission and become a useful tool.
In the MWE below, the routine \alphabubblesorter
calls on \sortlist
to do the primary bubble sort, with \picknext
being called upon for cases that share the same first letter. So \sortlist
is recursive through the data list, and \picknext
is recursive through the letter list of two comparitive entries.
\documentclass[10pt]{article}
\newcommand\alphabubblesort[1]{\def\sortedlist{}\expandafter\sortlist#1,9,\relax}
\def\sortlist#1#2,#3#4,#5\relax{%
\ifnum`#3=`9\relax%
\edef\sortedlist{\sortedlist#1#2}%
\else
\ifnum`#1<`#3\relax%
\edef\sortedlist{\sortedlist#1#2,}%
\sortlist#3#4,#5\relax%
\else%
\ifnum`#1>`#3\relax%
\let\tmp\sortedlist%
\def\sortedlist{}%
\expandafter\sortlist\tmp#3#4,#1#2,#5\relax%
\else%
\picknext#2!,#4!\relax%
\if F\flipflop%
\edef\sortedlist{\sortedlist#1#2,}%
\sortlist#3#4,#5\relax%
\else%
\let\tmp\sortedlist%
\def\sortedlist{}%
\expandafter\sortlist\tmp#3#4,#1#2,#5\relax%
\fi%
\fi%
\fi%
\fi%
}
\def\picknext#1#2,#3#4\relax{%
\ifnum`#1<`#3\relax
\xdef\flipflop{F}%
\else%
\ifnum`#1>`#3\relax%
\xdef\flipflop{T}%
\else%
\picknext#2!,#4!\relax%
\fi%
\fi%
}
\begin{document}
\alphabubblesort{da,cc,ca,eda,edc,edb,ef,ec,ed,eb,edzq,ba,e,fa,waaa,wa,qa}\sortedlist
\def\mydata{%
Spanish ,
ser ,
haber ,
estar ,
tener ,
hacer ,
poder ,
decir ,
ir ,
ver ,
dar ,
saber ,
querer ,
llegar ,
pasar ,
deber ,
poner ,
parecer ,
quedar ,
creer ,
hablar ,
llevar ,
dejar ,
seguir ,
%encontrar ,
llamar }
\alphabubblesort{\mydata}\sortedlist
\end{document}
encontrar
). Commented, it works; uncommented, it breaks.