BrainF* (697 bytes)
>>>>>>>>,[>,]<[[>>>+<<<-]>[<+>-]<+<]>[<<<<<<<<+>>>>>>>>-]<<<<<<<<[[>>+
>+>>+<<<<<-]>>[<<+>>-]<[>+>>+>>+<<<<<-]>[<+>-]>>>>[-<->]+<[>->+<<-[>>-
<<[-]]]>[<+>-]>[<<+>>-]<+<[->-<<[-]<[-]<<[-]<[[>+<-]<]>>[>]<+>>>>]>[-<
<+[-[>+<-]<-[>+<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<<]<<[>>+<<-]>[>[>+>
>+<<<-]>[<+>-]>>>>>>[<+<+>>-]<[>+<-]<<<[>+>[<-]<[<]>>[<<+>[-]+>-]>-<<-
]>>[-]+<<<[->>+<<]>>[->-<<<<<[>+<-]<[>+<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]
<<]>[[-]<<<<<<[>>+>>>>>+<<<<<<<-]>>[<<+>>-]>>>>>[-[>>[<<<+>>>-]<[>+<-]
<-[>+<-]>]<<[[>>+<<-]<]]>]<<<<<<-]>[>>>>>>+<<<<<<-]<<[[>>>>>>>+<<<<<<<
-]>[<+>-]<+<]<[[>>>>>>>>+<<<<<<<<-]>>[<+>-]<+<<]>+>[<-<<[>+<-]<[<]>[[<
+>-]>]>>>[<<<<+>>>>-]<<[<+>-]>>]<[-<<+>>]>>>]<<<<<<]>>>>>>>>>>>[.>]
Below is an annotated version. In order to keep track of what was supposed to be happening while developing it, I used a comment notation that looks like this: |a|b=0|c=A0|@d|A0|A1|```|
|a| represents a named cell
|b=X| means we know the cell has value X, where X can be a constant or a variable name
|@d| means the data pointer is in this cell
|A0|A1|```| is variable length array. (using ``` for ... because . is a command)
The memory is laid out with a left-growing stack of partitions to process on the left, a scratch space in the center, and the array being sorted to the right. Array indexing is handled by moving a "data bus" containing the index and working space through the array.
So for instance a 3-wide bus of |i|data|0|A0|A1|A2, will become |A0|i-1|data|0|A1|A2 after shifting by one. The partitioning is performed by keeping the bus between the high and low elements.
Here's the full version:
Get input
>>>>>>>> ,[>,] |A0|A1|```|An|@0|
Count items
<[ [>>>+<<<-]>[<+>-]<+ <] |@0|n|0|0|A0|A1|```
Make 8wide data bus w/ stack on left
>[<<<<<<<<+>>>>>>>>-] ```|K1=n|K0=0|Z=0|a|b|c|d|e|@f|g|X=0|A0|A1|```
K1 and K0 represent the first index to process (I) and one past the last (J)
Check if still partitions to process
<<<<<<<<[
Copy K1 to a&c via Z
[>>+>+>>+<<<<<-]>>[<<+>>-] ```|K1=J|K0=I|@Z=0|a=J|b|c=J|d|e|f|g|X=0|A0|A1|```
Copy K0 to b&d via Z
<[>+>>+>>+<<<<<-]>[<+>-] ```|K1|K0|@Z=0|a=J|b=I|c=J|d=I|e|f|g|X=0|A0|A1|```
Check if J minus I LE 1 : Subtract d from c
>>>>[-<->] |a=J|b=I|c=JminusI|@d=0|e|f|g|
d= c==0; e = c==1
+<[>- >+<<-[>>-<<[-]]] |a=J|b=I|@c=0|d=c==0|e=c==1|f|g|
if d or e is 1 then J minus I LE 1: partition empty
>[<+>-]>[<<+>>-]<+< |a=J|b=I|@c=isEmpty|d=1|e=0|f|g|
If Partition Empty;
[->- |a=J|b=I|@c=0|d=0|c=0|f|g|
pop K0: Zero it and copy the remaining stack right one; inc new K0
<<[-]<[-]<<[-]<[[>+<-]<]>>[>]<+ ``|K1|@Z=0|a=J|b=I|c=0|d=0|e|f|g|
Else:
>>>>]>[- Z|a=J|b=I|c=isEmpty=0|@d=0|e|f|g|X|A0|A1
Move Bus right I plus 1 frames; leaving first element to left
<<+[ -[>+<-]<-[>+<-]>>>>>>>> (dec J as we move)
[<<<<<<<<+>>>>>>>>-]<<<<<< ] Z|Ai|a=J|@b=0|c=0|d|e|f|g|X|Aq
first element becomes pivot Ap; store in b
<<[>>+<<-] Z|@0|a=J|b=Ap|c=0|d|e|f|g|X|Aq
While there are more elements (J GT 0);
>[ Z|0|@a=J|b=Ap|c=0|d|e|f|g|X|Aq
copy Ap to e via c
>[>+>>+<<<-]>[<+>-] Z|0|a=J|b=Ap|@c=0|d=0|e=Ap|f|g|X=0|Aq
copy Aq to g via X
>>>>>>[<+<+>>-]<[>+<-] |c|d=0|e=Ap|f|g=Aq|@X=0|Aq
Test Aq LT Ap: while e; mark f; clear it if g
<<<[ >+>[<-]<[<] |@d=0|e|f=gLTe|g|
if f: set d and e to 1; dec e and g
>>[<<+>[-]+>-]>-<<-]
set g to 1; if d: set f
>>[-]+<<< [->>+<<]
If Aq LT Ap move Aq across Bus
>>[->- <<<<<[>+<-] <[>+<-] >>>>>>>>
[<<<<<<<<+>>>>>>>>-] <<] Z|0|Aq|a=J|b=Ap|c|d|e|@f=0|g=0|X=0|Ar
Else Swap AQ w/ Aj: Build a 3wide shuttle holding J and Aq
>[[-] <<<<<<[>>+>>>>>+<<<<<<<-]>>[<<+>>-] |@c=0|d|e|f=0|g=0|X=J|Aq|Ar|```
If J then dec J
>>>>>[-
& While J shuttle right
[>>[<<<+>>>-]<[>+<-]<-[>+<-]>] |a=J|b=Ap|c|d|e|f|Ar|```|Aj|g=0|@X=0|Aq|
Leave Aq out there and bring Aj back
<<[ [>>+<<-] < ] |a=J|b=Ap|c|d|e|@f=0|g|X=0|Ar|```|Aj|Aq|
]>]
Either bus moved or last element swapped; reduce J in either case
<<<<<<-] |Aq|@a=0|b=Ap|c|d|e|f|g|X|Ar|```|
Insert Ap To right of bus
>[>>>>>>+<<<<<<-] |Aq|a=0|@b=0|c|d|e|f|g|Ap|Ar|```|
Move the bus back to original location tracking pivot location
<<[ [>>>>>>>+<<<<<<<-]>[<+>-]<+ <]
<[ [>>>>>>>>+<<<<<<<<-]>>[<+>-]<+ <<] |K1|K0|@Z=0|a=0|b=p|c|d|e|f|g|X|Ar|```
if p is not 0: put new partition on stack between K0 and K1:
>+>[<- |K1|K0|Z=0|@a=pEQ0|b=p|
move K0 to Z; search for last K
<<[>+<-] <[<] |@0|Kn|```|K1|0|Z=K0|a=0|b=p|
shift left until return to 0 at K0;
>[ [<+>-] >] |Kn|```|K1|0|@0|Z=K0|a=0|b=p|
put p one left of there making it K1; restore K0 from Z;
>>>[<<<<+>>>>-]<<[<+>-] |Kn|```|K2|K1=p|K0|@Z=0|a=0|b=0|
else increment K0 (special case when first partition empty)
>>]<[- <<+>>]
>>>] End if !empty
<<<<<<] End If Partitions remaining @K1=0|K0=0|Z=0|a|b|c|d|e|f|g|X=0|A0|A1|```
Print the Results
>>>>>>>>>>>[.>]