Sorting algorithms/Gnome sort

From Rosetta Code
Task
Sorting algorithms/Gnome sort
You are encouraged to solve this task according to the task description, using any language you may know.
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
    if a[i-1] <= a[i] # for descending sort, reverse the comparison to >=
        i := j
        j := j + 1 
    else
        swap a[i-1] and a[i]
        i := i - 1
        if i = 0
          i := j
          j := j + 1
 }

Task: implement the Gnome sort in your language to sort an array (or list) of numbers.

ALGOL 68

Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
Works with: ELLA ALGOL 68 version Any (with appropriate job cards AND formatted transput statements removed) - tested with release 1.8.8d.fc9.i386

<lang algol>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

BASIC

Works with: QuickBasic version 4.5
Translation of: C

<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;
   }
 }

}

  1. undef swap_</lang>

Java

Translation of: C

<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>

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>

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>

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 == 0
              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

<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>