Brainfuck (178 байт)
Даже если мозговитость громоздка, это помогает работать с зерном языка. Спросите себя "Должен ли я хранить это значение явно в ячейке?" Вы можете часто набирать скорость и краткость, делая что-то более тонкое. И когда значение является индексом массива (или произвольным натуральным числом), оно может не помещаться в ячейку. Конечно, вы можете просто принять это как ограничение вашей программы. Но разработка вашей программы для работы с большими значениями часто делает ее лучше другими способами.
Как обычно, моя первая рабочая версия была вдвое длиннее необходимой - 392 байта. Многочисленные модификации и два или три основных переписывания произвели эту сравнительно изящную 178-байтовую версию. (Хотя забавно, что сортировка по линейному времени составляет всего 40 байтов.)
>+>>>>>,[>+>>,]>+[--[+<<<-]<[[<+>-]<[<[->[<<<+>>>>+<-]<<[>>+>[->]<<[<]
<-]>]>>>+<[[-]<[>+<-]<]>[[>>>]+<<<-<[<<[<<<]>>+>[>>>]<-]<<[<<<]>[>>[>>
>]<+<<[<<<]>-]]+<<<]]+[->>>]>>]>[brainfuck.org>>>]
Входные значения располагаются через каждые три ячейки: для каждой ячейки (V) alue существует (L) ячейка abel (используется для навигации) и еще одна ячейка для (S) промежуточного пространства. Общая схема массива
0 1 0 0 0 SVLSVL ... SVL 0 0 0 0 0 0 ...
Первоначально все ячейки L установлены в 1, чтобы пометить части массива, которые все еще нуждаются в сортировке. Когда мы закончим разделение подмассива, мы разделим его на более мелкие подмассивы, установив L-ячейку его сводной ячейки в 0, затем найдем крайнюю правую L-ячейку, которая по-прежнему равна 1, и разделим эту подмассив дальше. Как ни странно, это все, что нам нужно для правильной обработки рекурсивной обработки подмассивов. Когда все L ячеек были обнулены, весь массив сортируется.
Чтобы разделить подмассив, мы вытягиваем его самое правое значение в S-ячейку, чтобы он действовал как свод, и переносим его (и соответствующую пустую V-ячейку) влево, сравнивая его друг с другом в подмассиве и меняя местами при необходимости. В конце, пивот возвращается обратно, используя тот же код подкачки (который экономит 50 байтов или около того). Во время разделения две дополнительные ячейки L сохраняются равными 0, чтобы пометить две ячейки, которые, возможно, необходимо поменять местами друг с другом; в конце разбиения левый 0 слится с 0 слева от подмассива, а правый 0 в конечном итоге помечает свою точку поворота. Этот процесс также оставляет лишнюю 1 в ячейке L справа от подмассива; основной цикл начинается и заканчивается в этой ячейке.
>+>>>>>,[>+>>,]>+[ 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