Sorting algorithms/Stooge sort
You are encouraged to solve this task according to the task description, using any language you may know.
Sorting Algorithm
This is a sorting algorithm. It may be applied to a set of data in order to sort it.
For comparing various sorts, see compare sorts.
For other sorting algorithms, see sorting algorithms, or:
Heap sort | Merge sort | Patience sort | Quick sort
O(n log2n) sorts
Shell Sort
O(n2) sorts
Bubble sort |
Cocktail sort |
Cocktail sort with shifting bounds |
Comb sort |
Cycle sort |
Gnome sort |
Insertion sort |
Selection sort |
Strand sort
other sorts
Bead sort |
Bogo sort |
Common sorted list |
Composite structures sort |
Custom comparator sort |
Counting sort |
Disjoint sublist sort |
External sort |
Jort sort |
Lexicographical sort |
Natural sorting |
Order by pair comparisons |
Order disjoint list items |
Order two numerical lists |
Object identifier (OID) sort |
Pancake sort |
Quickselect |
Permutation sort |
Radix sort |
Ranking methods |
Remove duplicate elements |
Sleep sort |
Stooge sort |
[Sort letters of a string] |
Three variable sort |
Topological sort |
Tree sort
This page uses content from Wikipedia. The original article was at Stooge sort. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
Show the Stooge Sort for an array of integers. The Stooge Sort algorithm is as follows:
algorithm stoogesort(array L, i = 0, j = length(L)-1) if L[j] < L[i] then L[i] ↔ L[j] if j - i > 1 then t := (j - i + 1)/3 stoogesort(L, i , j-t) stoogesort(L, i+t, j ) stoogesort(L, i , j-t) return L
C#
<lang C sharp|C#> public static void Sort<T>(List<T> list) where T : IComparable {
if (list.Count > 1) { StoogeSort(list, 0, list.Count - 1); } } private static void StoogeSort<T>(List<T> L, int i, int j) where T : IComparable { if (L[j].CompareTo(L[i])<0) { T tmp = L[i]; L[i] = L[j]; L[j] = tmp; } if (j - i > 1) { int t = (j - i + 1) / 3; StoogeSort(L, i, j - t); StoogeSort(L, i + t, j); StoogeSort(L, i, j - t); } }</lang>
D
<lang d>import std.stdio, std.algorithm;
void stoogeSort(T)(T[] seq) {
if (seq[$-1] < seq[0]) swap(seq[0], seq[$-1]);
if (seq.length > 2) { int m = seq.length / 3; stoogeSort(seq[0 .. $ - m]); stoogeSort(seq[m .. $]); stoogeSort(seq[0 .. $ - m]); }
}
void main() {
auto data = [1, 4, 5, 3, -6, 3, 7, 10, -2, -5]; stoogeSort(data); writeln(data);
}</lang>
Fortran
<lang fortran>program Stooge
implicit none
integer :: i integer :: array(50) = (/ (i, i = 50, 1, -1) /) ! Reverse sorted array call Stoogesort(array) write(*,"(10i5)") array
contains
recursive subroutine Stoogesort(a)
integer, intent(in out) :: a(:) integer :: j, t, temp j = size(a) if(a(j) < a(1)) then temp = a(j) a(j) = a(1) a(1) = temp end if
if(j > 2) then t = j / 3 call Stoogesort(a(1:j-t)) call Stoogesort(a(1+t:j)) call Stoogesort(a(1:j-t)) end if
end subroutine end program</lang>
Haskell
<lang haskell>import Data.List import Control.Arrow import Control.Monad
insertAt e k = uncurry(++).second ((e:).drop 1). splitAt k
swapElems :: [a] -> Int -> Int -> [a] swapElems xs i j = insertAt (xs!!j) i $ insertAt (xs!!i) j xs
stoogeSort [] = [] stoogeSort [x] = [x] stoogeSort xs = doss 0 (length xs - 1) xs doss :: (Ord a) => Int -> Int -> [a] -> [a] doss i j xs
| j-i>1 = doss i (j-t) $ doss (i+t) j $ doss i (j-t) xs' | otherwise = xs' where t = (j-i+1)`div`3
xs' | xs!!j < xs!!i = swapElems xs i j | otherwise = xs</lang> Example: <lang haskell>*Main> stoogeSort [1, 4, 5, 3, -6, 3, 7, 10, -2, -5, 7, 5, 9, -3, 7] [-6,-5,-3,-2,1,3,3,4,5,5,7,7,7,9,10]</lang>
Icon and Unicon
Icon
<lang Icon>procedure main() #: demonstrate various ways to sort a list and string
demosort(stoogesort,[3, 14, 1, 5, 9, 2, 6, 3],"qwerty")
end
procedure stoogesort(X,op,i,j) #: return sorted list ascending(or descending) local t
if /i := 0 then { j := *X op := sortop(op,X) # select how and what we sort }
if op(X[j],X[i]) then X[i] :=: X[j] if j - i > 1 then { t := (j - i + 1) / 3 X := stoogesort(X,op,i,j-t) X := stoogesort(X,op,i+t,j) X := stoogesort(X,op,i,j-t) } return X # X must be returned and assigned to sort a string
end</lang>
Note: This example relies on the supporting procedures 'sortop', and 'demosort' in Bubble Sort. The full demosort exercises the named sort of a list with op = "numeric", "string", ">>" (lexically gt, descending),">" (numerically gt, descending), a custom comparator, and also a string.
Abbreviated sample output:
Sorting Demo using procedure stoogesort on list : [ 3 14 1 5 9 2 6 3 ] with op = &null: [ 1 2 3 3 5 6 9 14 ] (0 ms) ... on string : "qwerty" with op = &null: "eqrtwy" (0 ms)
Unicon
The Icon solution works in Unicon.
J
<lang j>swapElems=: |.@:{`[`]}
stoogeSort=: 3 : 0
(0,<:#y) stoogeSort y
if. >/x{y do. y=.x swapElems y end. if. 1<-~/x do. t=. <.3%~1+-~/x (x-0,t) stoogeSort (x+t,0) stoogeSort (x-0,t) stoogeSort y else. y end.
)</lang> Example: <lang j> (,: stoogeSort) ?~13 3 10 8 4 7 12 1 2 11 6 5 9 0 0 1 2 3 4 5 6 7 8 9 10 11 12 </lang>
Java
<lang java>import java.util.Arrays;
public class Stooge {
public static void main(String[] args) { int[] nums = {1, 4, 5, 3, -6, 3, 7, 10, -2, -5}; stoogeSort(nums); System.out.println(Arrays.toString(nums)); }
public static void stoogeSort(int[] L) { stoogeSort(L, 0, L.length - 1); }
public static void stoogeSort(int[] L, int i, int j) { if (L[j] < L[i]) { int tmp = L[i]; L[i] = L[j]; L[j] = tmp; } if (j - i > 1) { int t = (j - i + 1) / 3; stoogeSort(L, i, j - t); stoogeSort(L, i + t, j); stoogeSort(L, i, j - t); } }
}</lang> Output:
[-6, -5, -2, 1, 3, 3, 4, 5, 7, 10]
MATLAB
<lang MATLAB>%Required inputs: %i = 1 %j = length(list) % function list = stoogeSort(list,i,j)
if list(j) < list(i) list([i j]) = list([j i]); end if (j - i) > 1 t = round((j-i+1)/3); list = stoogeSort(list,i,j-t); list = stoogeSort(list,i+t,j); list = stoogeSort(list,i,j-t); end
end</lang> Sample Output: <lang MATLAB>>> stoogeSort([1 -6 4 -9],1,4)
ans =
-9 -6 1 4</lang>
OCaml
<lang ocaml>let swap ar i j =
let tmp = ar.(i) in ar.(i) <- ar.(j); ar.(j) <- tmp
let stoogesort ar =
let rec aux i j = if ar.(j) < ar.(i) then swap ar i j else if j - i > 1 then begin let t = (j - i + 1) / 3 in aux (i) (j-t); aux (i+t) (j); aux (i) (j-t); end in aux 0 (Array.length ar - 1)</lang>
testing: <lang ocaml>let () =
let ar = [| 3; 1; 7; 2; 6; 5; 4; 9; 8 |] in stoogesort ar; Array.iter (Printf.printf " %d") ar; print_newline()</lang>
Oz
<lang oz>declare
proc {StoogeSort Arr} proc {Swap I J} Tmp = Arr.I in Arr.I := Arr.J Arr.J := Tmp end proc {Sort I J} Size = J-I+1 in if Arr.J < Arr.I then {Swap I J} end if Size >= 3 then Third = Size div 3 in {Sort I J-Third} {Sort I+Third J} {Sort I J-Third} end end in {Sort {Array.low Arr} {Array.high Arr}} end
Arr = {Tuple.toArray unit(1 4 5 3 ~6 3 7 10 ~2 ~5 7 5 9 ~3 7)}
in
{System.printInfo "\nUnsorted: "} for I in {Array.low Arr}..{Array.high Arr} do {System.printInfo Arr.I#", "} end
{StoogeSort Arr}
{System.printInfo "\nSorted : "} for I in {Array.low Arr}..{Array.high Arr} do {System.printInfo Arr.I#", "} end</lang>
Output:
Unsorted: 1, 4, 5, 3, -6, 3, 7, 10, -2, -5, 7, 5, 9, -3, 7, Sorted : -6, -5, -3, -2, 1, 3, 3, 4, 5, 5, 7, 7, 7, 9, 10,
Perl 6
<lang perl6>sub stoogesort( @L is rw, $i = 0, $j = @L.end ) {
@L[$j,$i] = @L[$i,$j] if @L[$i] > @L[$j];
my $interval = $j - $i; if $interval > 1 { my $t = ( $interval + 1 ) div 3; stoogesort( @L, $i , $j-$t ); stoogesort( @L, $i+$t, $j ); stoogesort( @L, $i , $j-$t ); } return @L;
}
my @L = 1, 4, 5, 3, -6, 3, 7, 10, -2, -5;
stoogesort(@L).Str.say; </lang>
PicoLisp
<lang PicoLisp>(de stoogeSort (L N)
(default N (length L)) (let P (nth L N) (when (> (car L) (car P)) (xchg L P) ) ) (when (> N 2) (let D (/ N 3) (stoogeSort L (- N D)) (stoogeSort (nth L (inc D)) (- N D)) (stoogeSort L (- N D)) ) ) L )</lang>
Test:
: (apply < (stoogeSort (make (do 100 (link (rand)))))) -> T
PL/I
<lang PL/I>stoogesort: procedure (L) recursive; /* 16 August 2010 */
declare L(*) fixed binary; declare (i, j, t, temp) fixed binary;
j = hbound(L,1); do i = lbound(L, 1) to j; if L(j) < L(i) then do; temp = L(i); L(i) = L(j); L(j) = temp; end; if j - i > 1 then do; t = (j - i + 1)/3; call stoogesort(L, i , j-t); call stoogesort(L, i+t, j ); call stoogesort(L, i , j-t); end; end;
end stoogesort;</lang>
PureBasic
<lang PureBasic>Procedure Stooge_Sort(Array L.i(1), i=0 , j=0)
If j=0 j=ArraySize(L()) EndIf If L(i)>L(j) Swap L(i), L(j) EndIf If j-i>1 Protected t=(j-i+1)/3 Stooge_Sort(L(), i, j-t) Stooge_Sort(L(), i+t, j ) Stooge_Sort(L(), i, j-t) EndIf
EndProcedure</lang> Implementation may be as<lang PureBasic>Define AmountOfPosts=(?Stop_Data-?Start_data)/SizeOf(Integer) Dim Xyz.i(AmountOfPosts) CopyMemory(?Start_data, @Xyz(), ?Stop_Data-?Start_data)
Stooge_Sort(Xyz())
For i=0 To ArraySize(Xyz())
Debug Xyz(i)
Next i
DataSection
Start_data: Data.i 1, 4, 5, 3, -6, 3, 7, 10, -2, -5, 7, 5, 9, -3, 7 Stop_Data:
EndDataSection</lang>
Python
<lang python>>>> data = [1, 4, 5, 3, -6, 3, 7, 10, -2, -5, 7, 5, 9, -3, 7] >>> def stoogesort(L, i=0, j=None): if j is None: j = len(L) - 1 if L[j] < L[i]: L[i], L[j] = L[j], L[i] if j - i > 1: t = (j - i + 1) // 3 stoogesort(L, i , j-t) stoogesort(L, i+t, j ) stoogesort(L, i , j-t) return L
>>> stoogesort(data) [-6, -5, -3, -2, 1, 3, 3, 4, 5, 5, 7, 7, 7, 9, 10]</lang>
This alternate solution uses a wrapper function to compute the initial value of j rather than detecting the sentinel value None. <lang python>>>> def stoogesort(L, i, j): if L[j] < L[i]: L[i], L[j] = L[j], L[i] if j - i > 1: t = (j - i + 1) // 3 stoogesort(L, i , j-t) stoogesort(L, i+t, j ) stoogesort(L, i , j-t) return L
>>> def stooge(L): return stoogesort(L, 0, len(L) - 1)
>>> data = [1, 4, 5, 3, -6, 3, 7, 10, -2, -5, 7, 5, 9, -3, 7] >>> stooge(data) [-6, -5, -3, -2, 1, 3, 3, 4, 5, 5, 7, 7, 7, 9, 10]</lang>
REXX
<lang REXX> /*REXX program to sort an integer array L, elements start at zero.*/
highItem=19 /*define a score of elements*/ widthH=length(highItem) /*width of biggest element#.*/ widthL=0 /*width of largest element. */
do k=0 to highItem /*populate the array. */ L.k=2*k + (k * -1**k) /*kinda generate randomish#.*/ if L.k==0 then L.k=-100-k /*if zero, make a negative# */ widthL=max(widthL,length(L.k)) /*compute max width so far. */ end
call showL 'before sort' /*show before array elements*/ call stoogeSort 0,highItem /*invoke the Stooge Sort. */ call showL ' after sort' /*show after array elements*/ exit
showL: sepLength=22+widthH+widthL /*compute seperator width. */ say copies('-',sepLength) /*show 1st seperator line. */
do j=0 to highItem say 'element' right(j,widthH) arg(1)":" right(L.j,widthL) end
say copies('=',sepLength) /*show 2nd seperator line. */ return
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ stoogeSort: procedure expose L.; parse arg i,j /*sort from I to J*/
if L.j<L.i then do /*swap L.i and L.j */
swap=L.i L.i=L.j L.j=swap end
if j-i>1 then do
t=(j-i+1)%3 /* % is integer division.*/ call stoogesort i , j-t call stoogesort i+t, j call stoogesort i , j-t end
return /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ </lang> Output:
---------------------------- element 0 before sort: -100 element 1 before sort: 1 element 2 before sort: 6 element 3 before sort: 3 element 4 before sort: 12 element 5 before sort: 5 element 6 before sort: 18 element 7 before sort: 7 element 8 before sort: 24 element 9 before sort: 9 element 10 before sort: 30 element 11 before sort: 11 element 12 before sort: 36 element 13 before sort: 13 element 14 before sort: 42 element 15 before sort: 15 element 16 before sort: 48 element 17 before sort: 17 element 18 before sort: 54 element 19 before sort: 19 ============================ ---------------------------- element 0 after sort: -100 element 1 after sort: 1 element 2 after sort: 3 element 3 after sort: 5 element 4 after sort: 6 element 5 after sort: 7 element 6 after sort: 9 element 7 after sort: 11 element 8 after sort: 12 element 9 after sort: 13 element 10 after sort: 15 element 11 after sort: 17 element 12 after sort: 18 element 13 after sort: 19 element 14 after sort: 24 element 15 after sort: 30 element 16 after sort: 36 element 17 after sort: 42 element 18 after sort: 48 element 19 after sort: 54 ============================
Smalltalk
<lang smalltalk>OrderedCollection extend [
stoogeSortFrom: i to: j [
(self at: j) < (self at: i) ifTrue: [ self swapElement: i with: j ]. j - i > 1
ifTrue: [
|t| t := (j - i + 1)//3. self stoogeSortFrom: i to: (j-t). self stoogeSortFrom: (i+t) to: j. self stoogeSortFrom: i to: (j-t)
] ] stoogeSort [ self stoogeSortFrom: 1 to: (self size) ] swapElement: i with: j [
|t| t := self at: i.
self at: i put: (self at: j).
self at: j put: t
]
].
|test| test := #( 1 4 5 3 -6 3 7 10 -2 -5) asOrderedCollection. test stoogeSort. test printNl.</lang>
Tcl
<lang tcl>package require Tcl 8.5
proc stoogesort {L {i 0} {j -42}} {
if {$j == -42} {# Magic marker set j [expr {[llength $L]-1}] } set Li [lindex $L $i] set Lj [lindex $L $j] if {$Lj < $Li} { lset L $i $Lj lset L $j $Li } if {$j-$i > 1} { set t [expr {($j-$i+1)/3}] set L [stoogesort $L $i [expr {$j-$t}]] set L [stoogesort $L [expr {$i+$t}] $j] set L [stoogesort $L $i [expr {$j-$t}]] } return $L
}
stoogesort {1 4 5 3 -6 3 7 10 -2 -5}</lang> Output:
-6 -5 -2 1 3 3 4 5 7 10
Yorick
Based on pseudocode, except using Yorick's 1-based arrays. Sorts in place. <lang yorick>func stoogesort(&L, i, j) {
if(is_void(i)) i = 1; if(is_void(j)) j = numberof(L); if(L(j) < L(i)) L([i,j]) = L([j,i]); if(j - i > 1) { t = (j - i + 1)/3; stoogesort, L, i, j-t; stoogesort, L, i+t, j; stoogesort, L, i, j-t; }
}</lang>
Example interactive use:
> foo = [1,4,5,3,-6,3,7,10,-2,-5] > stoogesort, foo > foo [-6,-5,-2,1,3,3,4,5,7,10]