正如在堆栈溢出休息室中所讨论的:
如果您无法以您最不了解的任何语言来实现en.wikipedia.org/wiki/Quicksort给出的Quicksort算法,则可能需要考虑其他职业。@sbi
但SBI还指出,也许BrainF ***是个例外。
因此,这是一个难题/挑战:在BrainF ***中实现QuickSort。实施必须
正如在堆栈溢出休息室中所讨论的:
如果您无法以您最不了解的任何语言来实现en.wikipedia.org/wiki/Quicksort给出的Quicksort算法,则可能需要考虑其他职业。@sbi
但SBI还指出,也许BrainF ***是个例外。
因此,这是一个难题/挑战:在BrainF ***中实现QuickSort。实施必须
Answers:
BrainF * (697字节)
>>>>>>>>,[>,]<[[>>>+<<<-]>[<+>-]<+<]>[<<<<<<<<+>>>>>>>>-]<<<<<<<<[[>>+
>+>>+<<<<<-]>>[<<+>>-]<[>+>>+>>+<<<<<-]>[<+>-]>>>>[-<->]+<[>->+<<-[>>-
<<[-]]]>[<+>-]>[<<+>>-]<+<[->-<<[-]<[-]<<[-]<[[>+<-]<]>>[>]<+>>>>]>[-<
<+[-[>+<-]<-[>+<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]<<<<<<]<<[>>+<<-]>[>[>+>
>+<<<-]>[<+>-]>>>>>>[<+<+>>-]<[>+<-]<<<[>+>[<-]<[<]>>[<<+>[-]+>-]>-<<-
]>>[-]+<<<[->>+<<]>>[->-<<<<<[>+<-]<[>+<-]>>>>>>>>[<<<<<<<<+>>>>>>>>-]
<<]>[[-]<<<<<<[>>+>>>>>+<<<<<<<-]>>[<<+>>-]>>>>>[-[>>[<<<+>>>-]<[>+<-]
<-[>+<-]>]<<[[>>+<<-]<]]>]<<<<<<-]>[>>>>>>+<<<<<<-]<<[[>>>>>>>+<<<<<<<
-]>[<+>-]<+<]<[[>>>>>>>>+<<<<<<<<-]>>[<+>-]<+<<]>+>[<-<<[>+<-]<[<]>[[<
+>-]>]>>>[<<<<+>>>>-]<<[<+>-]>>]<[-<<+>>]>>>]<<<<<<]>>>>>>>>>>>[.>]
下面是带注释的版本。为了跟踪开发过程中应该发生的情况,我使用了如下的注释符号:|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)
内存的布局是在左侧增加要处理的分区堆栈,在左侧是要处理的空间,中间是暂存空间,而数组则在右侧进行排序。通过在阵列中移动包含索引和工作空间的“数据总线”来处理阵列索引。因此,例如,3宽的公交车|i|data|0|A0|A1|A2
将|A0|i-1|data|0|A1|A2
在移位后变为。通过将总线保持在高低元素之间来执行分区。
这是完整版本:
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
>>>>>>>>>>>[.>]
if (i<j) {} else {}
也经过了几次尝试才能正确。边缘案例是杀手.。我不知道有多少次我想“仅剩一件小事……”,然后发现了一个测试用例,导致又要花几个小时才能处理。我认为我可以减少几十个字符,但是我不确定是否要付出努力。
脑干 (178字节)
即使Brainfuck很麻烦,也有助于使用该语言。问问自己“我是否必须在单元格中明确存储此值?” 您通常可以通过做一些更细微的事情来获得速度和简洁感。并且当值是数组索引(或任意自然数)时,它可能不适合单元格。当然,您可以接受它作为程序的限制。但是,设计程序以处理较大的值通常会使它在其他方面变得更好。
像往常一样,我的第一个工作版本是所需字节的两倍(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将结束标记其中心点。此过程还在子数组的右侧L单元中留下了额外的1;主循环在此单元格处开始和结束。
>+>>>>>,[>+>>,]>+[ 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