스택 오버플로의 라운지 룸에서 논의한 바와 같이 :
최소한의 지식만으로 en.wikipedia.org/wiki/Quicksort에 Quicksort 알고리즘을 구현할 수없는 경우 다른 직업을 고려할 수 있습니다. s
그러나 SBI는 또한 BrainF ***가 예외라고 지적했다.
여기 퍼즐 / 도전이 있습니다 : BrainF *** 에서 QuickSort를 구현하십시오 . 구현은 반드시
스택 오버플로의 라운지 룸에서 논의한 바와 같이 :
최소한의 지식만으로 en.wikipedia.org/wiki/Quicksort에 Quicksort 알고리즘을 구현할 수없는 경우 다른 직업을 고려할 수 있습니다. s
그러나 SBI는 또한 BrainF ***가 예외라고 지적했다.
여기 퍼즐 / 도전이 있습니다 : BrainF *** 에서 QuickSort를 구현하십시오 . 구현은 반드시
답변:
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 {}
. 그리고 가장 중요한 경우는 살인자입니다. 나는 "이 작은 일이 남았다 ..."라고 몇 번이나 생각한 다음 몇 시간 동안 처리해야하는 테스트 사례를 발견했다. 나는 그것을 12 문자로 줄일 수 있다고 생각하지만 노력을 기울이고 싶지는 않습니다.
brainfuck (178 바이트)
brainfuck가 번거 롭더라도 언어의 곡물을 다루는 데 도움이됩니다. "이 값을 셀에 명시 적으로 저장해야합니까?" 더 미묘한 일을함으로써 종종 속도와 결정을 얻을 수 있습니다. 그리고 값이 배열 인덱스 (또는 임의의 자연수) 인 경우 셀에 맞지 않을 수 있습니다 . 물론, 당신은 그것을 프로그램의 한계로 받아 들일 수 있습니다. 그러나 큰 값을 처리하도록 프로그램을 설계하면 다른 방식으로 개선하는 경우가 많습니다.
평소와 같이, 첫 번째 작업 버전은 392 바이트가 필요했던 것보다 2 배 길었습니다. 이 수정 된 178 바이트 버전은 수많은 수정 사항과 2 ~ 3 개의 주요 재 작성으로 작성되었습니다. (선명 하게 선형 시간 정렬 은 40 바이트에 불과합니다.)
>+>>>>>,[>+>>,]>+[--[+<<<-]<[[<+>-]<[<[->[<<<+>>>>+<-]<<[>>+>[->]<<[<]
<-]>]>>>+<[[-]<[>+<-]<]>[[>>>]+<<<-<[<<[<<<]>>+>[>>>]<-]<<[<<<]>[>>[>>
>]<+<<[<<<]>-]]+<<<]]+[->>>]>>]>[brainfuck.org>>>]
입력 값은 3 개의 셀마다 간격이 있습니다. (V) alue 셀마다 (L) abel 셀 (탐색에 사용됨)과 (S) cratch 공간에 대해 하나 이상의 셀이 있습니다. 배열의 전체 레이아웃은
01000 SVLSVL ... SVL 000 000 ... ...
처음에는 모든 L 셀이 1로 설정되어 정렬이 필요한 배열 부분을 표시합니다. 하위 배열을 분할 한 후에는 피벗의 L 셀을 0으로 설정하여 하위 배열을 더 작은 하위 배열로 나눈 다음 여전히 1 인 가장 오른쪽의 L 셀을 찾고 다음에 해당 하위 배열을 분할합니다. 이상하게도 이것은 하위 배열의 재귀 처리를 올바르게 처리하는 데 필요한 모든 부기입니다. 모든 L 셀이 0이되면 전체 배열이 정렬됩니다.
하위 배열을 분할하기 위해 가장 오른쪽 값을 S 셀로 가져와 피벗 역할을하고 하위 배열의 서로 다른 값과 비교하여 필요에 따라 스와핑하여 피벗 역할을합니다. 마지막으로 동일한 스왑 코드 (50 바이트 정도 절약)를 사용하여 피벗이 다시 스왑됩니다. 분할하는 동안, 2 개의 여분의 L 셀은 0으로 설정되어 서로 교환 될 필요가있는 2 개의 셀을 표시한다; 파티셔닝이 끝나면 왼쪽 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