Sorting algorithms/Gnome sort: Difference between revisions
Line 785: | Line 785: | ||
:DelVar Q |
:DelVar Q |
||
:Return |
:Return |
||
=={{header|VBScript}}== |
|||
<lang VBScript>function gnomeSort( a ) |
|||
dim i |
|||
dim j |
|||
i = 1 |
|||
j = 2 |
|||
do while i < ubound( a ) + 1 |
|||
if a(i-1) <= a(i) then |
|||
i = j |
|||
j = j + 1 |
|||
else |
|||
swap a(i-1), a(i) |
|||
i = i - 1 |
|||
if i = 0 then |
|||
i = j |
|||
j = j + 1 |
|||
end if |
|||
end if |
|||
loop |
|||
gnomeSort = a |
|||
end function |
|||
sub swap( byref x, byref y ) |
|||
dim temp |
|||
temp = x |
|||
x = y |
|||
y = temp |
|||
end sub</lang> |
|||
Usage: |
|||
<lang VBScript>dim a |
|||
dim b |
|||
a = array( "zanzibar", "aardvark","ampicillin","zulu","gogodala", "wolverhampton") |
|||
b = gnomeSort( a ) |
|||
wscript.echo join(a, ", ") |
|||
a = array( 234,567,345,568,2345,89,547,23,649,5769,456,456,567) |
|||
b = gnomeSort( a ) |
|||
wscript.echo join(a, ", ") |
|||
a = array( true, false, true, true, false, false, true, false) |
|||
b = gnomeSort( a ) |
|||
wscript.echo join(a, ", ") |
|||
a = array( 1,2,2,4,67789,-3,-45.99) |
|||
b = gnomeSort( a ) |
|||
wscript.echo join(a, ", ") |
|||
a = array( now(), now()-1,now()+2) |
|||
b = gnomeSort( a ) |
|||
wscript.echo join(a, ", ") |
|||
</lang> |
|||
Output: |
|||
<lang VBScript>aardvark, ampicillin, gogodala, wolverhampton, zanzibar, zulu |
|||
23, 89, 234, 345, 456, 456, 547, 567, 567, 568, 649, 2345, 5769 |
|||
True, True, True, True, False, False, False, False |
|||
-45.99, -3, 1, 2, 2, 4, 67789 |
|||
2/02/2010 10:19:51 AM, 3/02/2010 10:19:51 AM, 5/02/2010 10:19:51 AM</lang> |
|||
Note: All data in VBScript is of type Variant. Thus the code can sort many different types of data without code modification. |
|||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
Revision as of 02:19, 3 February 2010
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 Sorting algorithms/Gnome 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) |
Gnome sort is a sorting algorithm which is similar to Insertion sort, except that moving an element to its proper place is accomplished by a series of swaps, as in Bubble Sort.
The pseudocode for the algorithm is:
function gnomeSort(a[0..size-1]) i := 1 j := 2 while i < size do if a[i-1] <= a[i] then // for descending sort, use >= for comparison i := j j := j + 1 else swap a[i-1] and a[i] i := i - 1 if i = 0 then i := j j := j + 1 endif endif done
Task: implement the Gnome sort in your language to sort an array (or list) of numbers.
Ada
This example is a generic procedure for constrained array types. <lang Ada>generic
type Element_Type is private; type Index is (<>); type Collection is array(Index) of Element_Type; with function "<=" (Left, Right : Element_Type) return Boolean is <>;
procedure Gnome_Sort(Item : in out Collection);</lang>
<lang Ada>procedure Gnome_Sort(Item : in out Collection) is
procedure Swap(Left, Right : in out Element_Type) is Temp : Element_Type := Left; begin Left := Right; Right := Temp; end Swap; I : Integer := Index'Pos(Index'Succ(Index'First)); J : Integer := I + 1;
begin
while I <= Index'Pos(Index'Last) loop if Item(Index'Val(I - 1)) <= Item(Index'Val(I)) then I := J; J := J + 1; else Swap(Item(Index'Val(I - 1)), Item(Index'Val(I))); I := I - 1; if I = Index'Pos(Index'First) then I := J; J := J + 1; end if; end if; end loop;
end Gnome_Sort;</lang> Usage example: <lang Ada>with Gnome_Sort; with Ada.Text_Io; use Ada.Text_Io;
procedure Gnome_Sort_Test is
type Index is range 0..9; type Buf is array(Index) of Integer; procedure Sort is new Gnome_Sort(Integer, Index, Buf); A : Buf := (900, 700, 800, 600, 400, 500, 200, 100, 300, 0);
begin
for I in A'range loop Put(Integer'Image(A(I))); end loop; New_Line; Sort(A); for I in A'range loop Put(Integer'Image(A(I))); end loop; New_Line;
end Gnome_Sort_Test;</lang>
ALGOL 68
<lang algol68>MODE SORTSTRUCT = CHAR;
PROC inplace gnome sort = (REF[]SORTSTRUCT list)REF[]SORTSTRUCT: BEGIN
INT i:=LWB list + 1, j:=LWB list + 2; WHILE i <= UPB list DO IF list[i-1] <= list[i] THEN i := j; j+:=1 ELSE SORTSTRUCT swap = list[i-1]; list[i-1]:= list[i]; list[i]:= swap; i-:=1; IF i=LWB list THEN i:=j; j+:=1 FI FI OD; list
END;
PROC gnome sort = ([]SORTSTRUCT seq)[]SORTSTRUCT:
in place gnome sort(LOC[LWB seq: UPB seq]SORTSTRUCT:=seq);
[]SORTSTRUCT char array data = "big fjords vex quick waltz nymph"; print((gnome sort(char array data), new line))</lang> Output:
abcdefghiijklmnopqrstuvwxyz
AutoHotkey
contributed by Laszlo on the ahk forum <lang AutoHotkey>MsgBox % GnomeSort("") MsgBox % GnomeSort("xxx") MsgBox % GnomeSort("3,2,1") MsgBox % GnomeSort("dog,000000,xx,cat,pile,abcde,1,cat,zz,xx,z")
GnomeSort(var) { ; SORT COMMA SEPARATED LIST
StringSplit a, var, `, ; make array, size = a0 i := 2, j := 3 While i <= a0 { ; stop when sorted u := i-1 If (a%u% < a%i%) ; search for pairs to swap i := j, j := j+1 Else { ; swap t := a%u%, a%u% := a%i%, a%i% := t If (--i = 1) ; restart search i := j, j++ } } Loop % a0 ; construct string from sorted array sorted .= "," . a%A_Index% Return SubStr(sorted,2) ; drop leading comma
}</lang>
BASIC
<lang qbasic>dim a(0 to n-1) as integer '...more code... sort: i = 1 j = 2
while(i < ubound(a) - lbound(a))
if a(i-1) <= a(i) then i = j j = j + 1 else swap a(i-1), a(i) i = i - 1 if i = 0 then i = j j = j + 1 end if end if
wend</lang>
C
This algorithm sorts in place modifying the passed array (of n integer numbers).
<lang c>#define swap_(I,J) do { int t_; t_ = a[(I)]; \
a[(I)] = a[(J)]; a[(J)] = t_; } while(0)
void gnome_sort(int *a, int n) {
int i=1, j=2; while(i < n) { if ( a[i-1] <= a[i] ) { i = j; j++; } else { swap_(i-1, i); i--; i = (i==0) ? j++ : i; } }
}
- undef swap_</lang>
C#
<lang csharp>public static void gnomeSort(ref int[] a) {
int i = 1; int j = 2;
while (i < a.Length) { if (a[i - 1] <= a[i]) { i = j; j++; } else { int tmp = a[i - 1]; a[i - 1] = a[i]; a[i--] = tmp; i = (i == 0) ? j++ : i; } } }
}</lang>
C++
Compiler: g++ (version 4.3.2 20081105 (Red Hat 4.3.2-7))
<lang cpp>#include <algorithm>
- include <iterator>
template<typename RandomAccessIterator> void gnomeSort(RandomAccessIterator begin, RandomAccessIterator end) {
RandomAccessIterator i = begin + 1; RandomAccessIterator j = begin + 2;
while(i < end) { if(*(i - 1) <= *i) { i = j; ++j; } else { std::iter_swap(i - 1, i); --i; if(i == begin) { i = j; ++j; } } }
}</lang>
Clojure
<lang lisp>(defn gnomesort
([c] (gnomesort c <)) ([c pred] (if (empty? c) c (loop [x [] y c] (cond (empty? y) x (empty? x) (recur (take 1 y) (rest y)) true (let [y1 (first y) ys (rest y) zx (last x)] (if (pred y1 zx) (recur (butlast x) (concat (list y1 zx) ys)) (recur (concat x (list y1)) ys))))))))
</lang>
Common Lisp
<lang lisp>(defun gnome-sort (array predicate &aux (length (length array)))
(do ((position (min 1 length))) ((eql length position) array) (cond ((eql 0 position) (incf position)) ((funcall predicate (aref array position) (aref array (1- position))) (rotatef (aref array position) (aref array (1- position))) (decf position)) (t (incf position)))))</lang>
E
<lang e>def gnomeSort(array) {
var size := array.size() var i := 1 var j := 2 while (i < size) { if (array[i-1] <= array[i]) { i := j j += 1 } else { def t := array[i-1] array[i-1] := array[i] array[i] := t i -= 1 if (i <=> 0) { i := j j += 1 } } }
}</lang>
<lang e>? def a := [7,9,4,2,1,3,6,5,0,8].diverge()
- value: [7, 9, 4, 2, 1, 3, 6, 5, 0, 8].diverge()
? gnomeSort(a) ? a
- value: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].diverge()</lang>
F#
<lang fsharp> let inline gnomeSort (a: _ []) =
let rec loop i j = if i < a.Length then if a.[i-1] <= a.[i] then loop j (j+1) else let t = a.[i-1] a.[i-1] <- a.[i] a.[i] <- t if i=1 then loop j (j+1) else loop (i-1) j loop 1 2
</lang>
Fortran
<lang fortran>program example
implicit none integer :: array(8) = (/ 2, 8, 6, 1, 3, 5, 4, 7 /)
call Gnomesort(array) write(*,*) array
contains
subroutine Gnomesort(a)
integer, intent(in out) :: a(:) integer :: i, j, temp
i = 2 j = 3 do while (i <= size(a)) if (a(i-1) <= a(i)) then i = j j = j + 1 else temp = a(i-1) a(i-1) = a(i) a(i) = temp i = i - 1 if (i == 1) then i = j j = j + 1 end if end if end do
end subroutine Gnomesort
end program example</lang>
Haskell
<lang haskell>gnomeSort [] = [] gnomeSort xs = gs [] xs
where gs xs [] = xs gs [] (y:ys) = gs [y] ys gs xs (y:ys) | y < zx = gs (init xs) (y:zx:ys) | otherwise = gs (xs++[y]) ys where zx = last xs</lang>
Example (executed in GHCi): <lang haskell>~> gnomeSort [7,2,4,3] [2,3,4,7]</lang>
J
<lang J>position=: 0 {.@I.@, [ swap=: ] A.~ *@position * #@[ !@- <:@position gnome=: swap~ 2 >/\ ] gnomes=: gnome^:_</lang>
Note 1: this implementation of swap is actually rather silly, and will not work on long lists. A better implementation would be:<lang J>swap=: position (] {~ _1 0 + [)`(0 _1 + [)`]}^:(*@[) ]</lang>
Note 2: this implementation only works for domains where > is defined (in J, "greater than" only works on numbers). To work around this issue, you could define:<lang J>gt=: -.@(-: /:~)@,&< gnome=: swap~ 2 gt/\ ]</lang>
Note 3: this implementation does not return intermediate results. If you want them, you could use<lang J>gnomeps=: gnome^:a:</lang>
Note 4: gnomeps just shows intermediate results and does not show the gnome's position. You can extract the gnome's position using an expression such as<lang J>2 ~:/\ gnomeps</lang>.
Java
<lang java>public static void gnomeSort(int[] a) {
int i=1; int j=2; while(i < a.length) { if ( a[i-1] <= a[i] ) { i = j; j++; } else { int tmp = a[i-1]; a[i-1] = a[i]; a[i--] = tmp; i = (i==0) ? j++ : i; } }
}</lang>
Lua
Keep in mind that Lua arrays initial index is 1. <lang lua>function gnomeSort(a)
local i, j = 2, 3
while i < #a do if a[i-1] <= a[i] then i = j j = j + 1 else a[i-1], a[i] = a[i], a[i-1] -- swap i = i - 1 if i == 1 then -- 1 instead of 0 i = j j = j + 1 end end end
end</lang> Example: <lang lua>list = { 5, 6, 1, 2, 9, 14, 2, 15, 6, 7, 8, 97 } gnomeSort(list) for i, j in pairs(list) do
print(j)
end</lang>
Metafont
<lang metafont>def gnomesort(suffix v)(expr n) = begingroup save i, j, t;
i := 1; j := 2; forever: exitif not (i < n); if v[i-1] <= v[i]: i := j; j := j + 1; else: t := v[i-1]; v[i-1] := v[i]; v[i] := t; i := i - 1; i := if i=0: j; j := j + 1 else: i fi; fi endfor
endgroup enddef;</lang>
<lang metafont>numeric a[]; for i = 0 upto 9: a[i] := uniformdeviate(40); message decimal a[i]; endfor message char10;
gnomesort(a, 10); for i = 0 upto 9: message decimal a[i]; endfor end</lang>
OCaml
from the toplevel: <lang ocaml># let gnome_sort a =
let i = ref 1 and j = ref 2 in while !i < Array.length a do if a.(!i-1) <= a.(!i) then begin i := !j; j := !j + 1; end else begin swap a (!i-1) (!i); i := !i - 1; if !i = 0 then begin i := !j; j := !j + 1; end; end; done; ;;
val gnome_sort : 'a array -> unit = <fun>
- let a = [| 7; 9; 4; 2; 1; 3; 6; 5; 0; 8; |] ;;
val a : int array = [|7; 9; 4; 2; 1; 3; 6; 5; 0; 8|]
- gnome_sort a ;;
- : unit = ()
- a ;;
- : int array = [|0; 1; 2; 3; 4; 5; 6; 7; 8; 9|]</lang>
Octave
<lang octave>function s = gnomesort(v)
i = 2; j = 3; while ( i <= length(v) ) if ( v(i-1) <= v(i) ) i = j; j++; else t = v(i-1); v(i-1) = v(i); v(i) = t; i--; if ( i == 1 )
i = j; j++;
endif endif endwhile s = v;
endfunction</lang>
<lang octave>v = [7, 9, 4, 2, 1, 3, 6, 5, 0, 8]; disp(gnomesort(v));</lang>
Pascal
<lang pascal>procedure gnomesort(var arr : Array of Integer; size : Integer); var
i, j, t : Integer;
begin
i := 1; j := 2; while i < size do begin if arr[i-1] <= arr[i] then begin
i := j; j := j + 1
end else begin
t := arr[i-1]; arr[i-1] := arr[i]; arr[i] := t; i := i - 1; if i = 0 then begin i := j; j := j + 1 end
end end;
end;</lang>
Perl
<lang perl>use strict;
sub gnome_sort {
my @a = @_;
my $size = scalar(@a); my $i = 1; my $j = 2; while($i < $size) {
if ( $a[$i-1] <= $a[$i] ) { $i = $j; $j++; } else { @a[$i, $i-1] = @a[$i-1, $i]; $i--; if ($i == 0) { $i = $j; $j++; } }
} return @a;
}</lang>
<lang perl>my @arr = ( 10, 9, 8, 5, 2, 1, 1, 0, 50, -2 ); print "$_\n" foreach gnome_sort( @arr );</lang>
Perl 6
<lang perl6>sub gnome_sort (@a is rw) {
my ($i, $j) = 1, 2; while $i < @a { if @a[$i - 1] <= @a[$i] { $i, $j = $j, $j + 1; } else { @a[$i - 1], @a[$i] = @a[$i], @a[$i - 1]; --$i or $i, $j = $j, $j + 1; } }
}</lang>
PowerBASIC
The BASIC example will work as-is if the array is declared in the same function as the sort. This example doesn't require that, but forces you to know your data type beforehand.
<lang powerbasic>SUB gnomeSort (a() AS LONG)
DIM i AS LONG, j AS LONG i = 1 j = 2 WHILE (i < UBOUND(a) + 1) IF (a(i - 1) <= a(i)) THEN i = j INCR j ELSE SWAP a(i - 1), a(i) DECR i IF 0 = i THEN i = j INCR j END IF END IF WEND
END SUB
FUNCTION PBMAIN () AS LONG
DIM n(9) AS LONG, x AS LONG RANDOMIZE TIMER OPEN "output.txt" FOR OUTPUT AS 1 FOR x = 0 TO 9 n(x) = INT(RND * 9999) PRINT #1, n(x); ","; NEXT PRINT #1, gnomeSort n() FOR x = 0 TO 9 PRINT #1, n(x); ","; NEXT CLOSE 1
END FUNCTION</lang>
Sample output:
7426 , 7887 , 8297 , 2671 , 7586 , 7160 , 1195 , 665 , 9352 , 6199 , 665 , 1195 , 2671 , 6199 , 7160 , 7426 , 7586 , 7887 , 8297 , 9352 ,
Python
<lang python>>>> def gnomesort(a): i,j,size = 1,2,len(a) while i < size: if a[i-1] <= a[i]: i,j = j, j+1 else: a[i-1],a[i] = a[i],a[i-1] i -= 1 if i == 0: i,j = j, j+1 return a
>>> gnomesort([3,4,2,5,1,6]) [1, 2, 3, 4, 5, 6] >>></lang>
R
<lang r>gnomesort <- function(x) {
i <- 1 j <- 1 while(i < length(x)) { if(x[i] <= x[i+1]) { i <- j j <- j+1 } else { temp <- x[i] x[i] <- x[i+1] x[i+1] <- temp i <- i - 1 if(i == 0) { i <- j j <- j+1 } } } x
} gnomesort(c(4, 65, 2, -31, 0, 99, 83, 782, 1)) # -31 0 1 2 4 65 83 99 782</lang>
Ruby
<lang ruby>class Array
def gnomesort! i, j = 1, 2 while i < length if self[i-1] <= self[i] i, j = j, j+1 else self[i-1], self[i] = self[i], self[i-1] i -= 1 if i == 0 i, j = j, j+1 end end end self end
end ary = [7,6,5,9,8,4,3,1,2,0] ary.gnomesort!
- => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</lang>
Smalltalk
<lang smalltalk>Smalltalk at: #gnomesort put: nil.
"Utility" OrderedCollection extend [
swap: a with: b [ |t| t := self at: a. self at: a put: b. self at: b put: t ]
].
"Gnome sort as block closure" gnomesort := [ :c |
|i j| i := 2. j := 3. [ i <= (c size) ] whileTrue: [ (c at: (i-1)) <= (c at: i) ifTrue: [ i := j copy. j := j + 1. ] ifFalse: [ c swap: (i-1) with: i. i := i - 1. i == 1 ifTrue: [ i := j copy. j := j + 1 ] ] ]
].</lang>
Testing
<lang smalltalk>|r o| r := Random new. o := OrderedCollection new.
1 to: 10 do: [ :i | o add: (r between: 0 and: 50) ].
gnomesort value: o.
1 to: 10 do: [ :i | (o at: i) displayNl ].</lang>
Tcl
Uses struct::list
package from
<lang tcl>package require Tcl 8.5 package require struct::list
proc gnomesort {a} {
set i 1 set j 2 set size [llength $a] while {$i < $size} { if {[lindex $a [expr {$i - 1}]] <= [lindex $a $i]} { set i $j incr j } else { struct::list swap a [expr {$i - 1}] $i incr i -1 if {$i == 0} { set i $j incr j } } } return $a
}
puts [gnomesort {8 6 4 2 1 3 5 7 9}] ;# => 1 2 3 4 5 6 7 8 9</lang>
TI-83 BASIC
Store input into L1, run prgmSORTGNOM, output will be in L2.
:1→P :L1→L2 :While P<dim(L2) :If PP=1 :Then :P+1→P :Else :If L2(P)≥L2(P-1) :Then :P+1→P :Else :L2(P)→Q :L2(P-1)→L2(P) :Q→L2(P-1) :P-1→P :End :End :End :If L2(dim(L2))<L2(dim(L2)-1) :Then :L2(dim(L2))→Q :L2(dim(L2)-1)→L2(dim(L2)) :Q→L2(dim(L2)-1) :End :DelVar P :DelVar Q :Return
VBScript
<lang VBScript>function gnomeSort( a ) dim i dim j i = 1 j = 2 do while i < ubound( a ) + 1 if a(i-1) <= a(i) then i = j j = j + 1 else swap a(i-1), a(i) i = i - 1 if i = 0 then i = j j = j + 1 end if end if loop gnomeSort = a end function
sub swap( byref x, byref y ) dim temp temp = x x = y y = temp end sub</lang> Usage: <lang VBScript>dim a dim b
a = array( "zanzibar", "aardvark","ampicillin","zulu","gogodala", "wolverhampton") b = gnomeSort( a ) wscript.echo join(a, ", ")
a = array( 234,567,345,568,2345,89,547,23,649,5769,456,456,567) b = gnomeSort( a ) wscript.echo join(a, ", ")
a = array( true, false, true, true, false, false, true, false) b = gnomeSort( a ) wscript.echo join(a, ", ")
a = array( 1,2,2,4,67789,-3,-45.99) b = gnomeSort( a ) wscript.echo join(a, ", ")
a = array( now(), now()-1,now()+2) b = gnomeSort( a ) wscript.echo join(a, ", ") </lang> Output: <lang VBScript>aardvark, ampicillin, gogodala, wolverhampton, zanzibar, zulu 23, 89, 234, 345, 456, 456, 547, 567, 567, 568, 649, 2345, 5769 True, True, True, True, False, False, False, False -45.99, -3, 1, 2, 2, 4, 67789 2/02/2010 10:19:51 AM, 3/02/2010 10:19:51 AM, 5/02/2010 10:19:51 AM</lang> Note: All data in VBScript is of type Variant. Thus the code can sort many different types of data without code modification.
Ursala
The function is parameterized by a relational predicate and operates on a list. The algorithm is to scan forward until finding an item out of order, bubble it backwards to its proper position and resume scanning forward from where it was. <lang Ursala>gnome_sort "p" =
@NiX ^=lx -+ # iteration
~&r?\~& @lNXrX ->llx2rhPlrPCTxPrtPX~&lltPlhPrCXPrX ~&ll&& @llPrXh not "p", # backward bubble ->~&rhPlCrtPX ~&r&& ~&lZ!| @bh "p"+- # forward scan</lang>
Most of the code is wasted on dull but unavoidable stack manipulations. Here is a test program using the lexical partial order relation. <lang Ursala>#import std
- cast %s
t = gnome_sort(lleq) 'dfijhkwlawfkjnksdjnoqwjefgflkdsgioi'</lang> output:
'adddeffffgghiiijjjjkkkkllnnooqsswww'