brainfuck (178 bytes)
Mesmo se o cérebro for pesado, ajuda a trabalhar com os grãos da linguagem. Pergunte a si mesmo "Preciso armazenar esse valor explicitamente em uma célula?" Muitas vezes você pode ganhar velocidade e concisão fazendo algo mais sutil. E quando o valor é um índice de matriz (ou um número natural arbitrário), pode não caber em uma célula. Obviamente, você pode aceitar isso como um limite do seu programa. Mas projetar seu programa para lidar com grandes valores geralmente o tornará melhor de outras maneiras.
Como sempre, minha primeira versão de trabalho tinha o dobro do tempo necessário - 392 bytes. Numerosas modificações e duas ou três grandes regravações produziram esta versão de 178 bytes, relativamente simples. (Embora divertidamente uma classificação em tempo linear tenha apenas 40 bytes.)
>+>>>>>,[>+>>,]>+[--[+<<<-]<[[<+>-]<[<[->[<<<+>>>>+<-]<<[>>+>[->]<<[<]
<-]>]>>>+<[[-]<[>+<-]<]>[[>>>]+<<<-<[<<[<<<]>>+>[>>>]<-]<<[<<<]>[>>[>>
>]<+<<[<<<]>-]]+<<<]]+[->>>]>>]>[brainfuck.org>>>]
Os valores de entrada são espaçados a cada três células: para cada célula de valor (V), há uma célula (L) abel (usada para navegação) e mais uma célula para (S) espaço de crachá. O layout geral da matriz é
0 1 0 0 0 SVLSVL ... SVL 0 0 0 0 0 0 0 ...
Inicialmente, todas as células L são definidas como 1, para marcar partes da matriz que ainda precisam ser classificadas. Quando terminamos de particionar um subarray, o dividimos em subarrays menores, definindo a célula L de seu pivô como 0, depois localize a célula L mais à direita que ainda é 1 e particione o subarray em seguida. Estranhamente, essa é toda a contabilidade de que precisamos para lidar adequadamente com o processamento recursivo de subarrays. Quando todas as células L foram zeradas, toda a matriz é classificada.
Para particionar um subarray, puxamos seu valor mais à direita em uma célula S para atuar como pivô e o trazemos (e a célula V vazia correspondente) para a esquerda, comparando-o com o outro valor no subarray e trocando conforme necessário. No final, o pivô é trocado novamente, usando o mesmo código de troca (que economiza 50 bytes ou mais). Durante o particionamento, duas células L extras são mantidas definidas como 0, para marcar as duas células que podem precisar ser trocadas entre si; no final do particionamento, o 0 esquerdo se fundirá com o 0 à esquerda da sub-matriz e o 0 direito terminará marcando seu pivô. Esse processo também deixa 1 extra na célula L à direita do subarray; o loop principal começa e termina nesta célula.
>+>>>>>,[>+>>,]>+[ set up; for each subarray:
--[+<<<-]<[ find the subarray; if it exists:
[<+>-]<[ S=pivot; while pivot is in S:
<[ if not at end of subarray
->[<<<+>>>>+<-] move pivot left (and copy it)
<<[>>+>[->]<<[<]<-]> move value to S and compare with pivot
]>>>+<[[-]<[>+<-]<]>[ if pivot greater then set V=S; else:
[>>>]+<<<-<[<<[<<<]>>+>[>>>]<-] swap smaller value into V
<<[<<<]>[>>[>>>]<+<<[<<<]>-] swap S into its place
]+<<< end else and set S=1 for return path
] subarray done (pivot was swapped in)
]+[->>>]>> end "if subarray exists"; go to right
]>[brainfuck.org>>>] done sorting whole array; output it