I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Sorting algorithms/Cocktail sort with shifting bounds

Sorting algorithms/Cocktail sort with shifting bounds
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:

O(n logn) sorts

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

 This page uses content from Wikipedia. The original article was at Cocktail 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)

The   cocktail sort   is an improvement on the   Bubble Sort.

A cocktail sort is also known as:

•   cocktail shaker sort
•   happy hour sort
•   bidirectional bubble sort
•   a bubble sort variation
•   a selection sort variation
•   ripple sort
•   shuffle sort
•   shuttle sort

The improvement is basically that values "bubble"   (migrate)   both directions through the array,   because on each iteration the cocktail sort   bubble sorts   once forwards and once backwards.

After   ii   passes,   the first   ii   and the last   ii   elements in the array are in their correct positions,   and don't have to be checked (again).

By shortening the part of the array that is sorted each time,   the number of comparisons can be halved.

Pseudocode for the   2nd   algorithm   (from Wikipedia)   with an added comment and changed indentations:

`function A = cocktailShakerSort(A)% `beginIdx` and `endIdx` marks the first and last index to check.beginIdx = 1;endIdx = length(A) - 1;     while beginIdx <= endIdx    newBeginIdx = endIdx;    newEndIdx = beginIdx;        for ii = beginIdx:endIdx            if A(ii) > A(ii + 1)                [A(ii+1), A(ii)] = deal(A(ii), A(ii+1));                newEndIdx = ii;            end        end     % decreases `endIdx` because the elements after `newEndIdx` are in correct order    endIdx = newEndIdx - 1;     % (FOR  (below)  decrements the  II  index by -1.         for ii = endIdx:-1:beginIdx            if A(ii) > A(ii + 1)                [A(ii+1), A(ii)] = deal(A(ii), A(ii+1));                newBeginIdx = ii;            end        end     % increases `beginIdx` because the elements before `newBeginIdx` are in correct order.    beginIdx = newBeginIdx + 1;    endend`

%   indicates a comment,   and   deal   indicates a   swap.

Implement a   cocktail sort   and optionally show the sorted output here on this page.

See the   discussion   page for some timing comparisons.

## 11l

Translation of: Python
`F cocktailshiftingbounds(&A)   V beginIdx = 0   V endIdx = A.len - 1    L beginIdx <= endIdx      V newBeginIdx = endIdx      V newEndIdx = beginIdx      L(ii) beginIdx .< endIdx         I A[ii] > A[ii + 1]            swap(&A[ii + 1], &A[ii])            newEndIdx = ii      endIdx = newEndIdx       L(ii) (endIdx .< beginIdx - 1).step(-1)         I A[ii] > A[ii + 1]            swap(&A[ii + 1], &A[ii])            newBeginIdx = ii      beginIdx = newBeginIdx + 1 V test1 = [7, 6, 5, 9, 8, 4, 3, 1, 2, 0]cocktailshiftingbounds(&test1)print(test1)`
Output:
```[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```

## 360 Assembly

For maximum compatibility, this program uses only the basic instruction set. The program uses also HLASM structured macros (DO,ENDDO,IF,ELSE,ENDIF) for readability and two ASSIST/360 macros (XDECO,XPRNT) to keep the code as short as possible.

`*        Cocktail sort with shifting bounds 10/05/2020COCKSHIS CSECT         USING  COCKSHIS,R13       base register         B      72(R15)            skip savearea         DC     17F'0'             savearea         SAVE   (14,12)            save previous context         ST     R13,4(R15)         link backward         ST     R15,8(R13)         link forward         LR     R13,R15            set addressability* Sort         LA     R0,1               1         ST     R0,BEGIDX          begIdx=LBound(A)         L      R0,N               n         BCTR   R0,0               n-1         ST     R0,ENDIDX          endIdx=UBound(A)-1         L      R1,BEGIDX          begIdx    DO WHILE=(C,R1,LE,ENDIDX)      while begIdx<=endIdx         MVC    NWBEGIDX,ENDIDX      nwbegIdx=endIdx         MVC    NWENDIDX,BEGIDX      nwendIdx=begIdx         L      RI,BEGIDX            i=begIdx    DO WHILE=(C,RI,LE,ENDIDX)        do i=1 to endIdx         LR     R1,RI                  i         SLA    R1,2                   .         LA     R2,A-4(R1)             @a(i)         LA     R3,A(R1)               @a(i+1)         L      R4,0(R2)               r4=a(i)         L      R5,0(R3)               r5=a(i+1)       IF    CR,R4,GT,R5 THEN          if a(i)>a(i+1) then         ST     R5,0(R2)                 a(i)=r5         ST     R4,0(R3)                 a(i+1)=r4         ST     RI,NWENDIDX              nwendIdx=i       ENDIF    ,                      end if         LA     RI,1(RI)               i=i+1    ENDDO       ,                    end do         L      R1,NWENDIDX          nwendIdx         BCTR   R1,0                 -1         ST     R1,ENDIDX            endIdx=nwendIdx-1         LR     RI,R1                endIdx    DO WHILE=(C,RI,GE,BEGIDX)        do i=endIdx to begIdx by -1         LR     R1,RI                  i         SLA    R1,2                   .         LA     R2,A-4(R1)             @a(i)         LA     R3,A(R1)               @a(i+1)         L      R4,0(R2)               r4=a(i)         L      R5,0(R3)               r5=a(i+1)       IF    CR,R4,GT,R5 THEN          if a(i)>a(i+1) then         ST     R5,0(R2)                 a(i)=r5         ST     R4,0(R3)                 a(i+1)=r4         ST     RI,NWBEGIDX              nwbegIdx=i               ENDIF    ,                      end if         BCTR   RI,0                   i=i-1    ENDDO       ,                    end do         L      R1,NWBEGIDX          nwbegIdx         LA     R1,1(R1)             +1         ST     R1,BEGIDX            begIdx=nwbegIdx+1    ENDDO       ,                  endwhile* Display sorted list         LA     R3,PG              pgi=0         LA     RI,1               i=1       DO     WHILE=(C,RI,LE,N)    do i=1 to n         LR     R1,RI                i         SLA    R1,2                 .         L      R2,A-4(R1)           a(i)         XDECO  R2,XDEC              edit a(i)         MVC    0(4,R3),XDEC+8       output a(i)         LA     R3,4(R3)             pgi=pgi+4         LA     RI,1(RI)             i=i+1       ENDDO    ,                  end do         XPRNT  PG,L'PG            print buffer         L      R13,4(0,R13)       restore previous savearea pointer         RETURN (14,12),RC=0       restore registers from calling saveA        DC     F'4',F'65',F'2',F'-31',F'0',F'99',F'2',F'83'          DC     F'782',F'1',F'45',F'82',F'69',F'82',F'104',F'58'         DC     F'88',F'112',F'89',F'74'N        DC     A((N-A)/L'A)       number of items of aPG       DC     CL80' '            bufferXDEC     DS     CL12               temp for xdecoBEGIDX   DS     F                  begIdxENDIDX   DS     F                  endIdxNWBEGIDX DS     F                  nwbegIdxNWENDIDX DS     F                  nwendIdx         REGEQURI       EQU    6                  i         END    COCKSHIS `
Output:
``` -31   0   1   2   2   4  45  58  65  69  74  82  82  83  88  89  99 104 112 782
```

## AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
` /* ARM assembly AARCH64 Raspberry PI 3B *//*  program cocktailSortbound64.s  */ /*******************************************//* Constantes file                         *//*******************************************//* for this file see task include a file in language AArch64 assembly */.include "../includeConstantesARM64.inc" /*********************************//* Initialized data              *//*********************************/.dataszMessSortOk:       .asciz "Table sorted.\n"szMessSortNok:      .asciz "Table not sorted !!!!!.\n"sMessResult:        .asciz "Value  : @ \n"szCarriageReturn:   .asciz "\n" .align 4//TableNumber:      .quad   1,3,6,2,5,9,10,8,4,7TableNumber:     .quad   10,9,8,7,6,-5,4,3,2,1                 .equ NBELEMENTS, (. - TableNumber) / 8 /*********************************//* UnInitialized data            *//*********************************/.bsssZoneConv:       .skip 24/*********************************//*  code section                 *//*********************************/.text.global main main:                                              // entry of program     ldr x0,qAdrTableNumber                         // address number table    mov x1,0    mov x2,NBELEMENTS                              // number of élements     bl cocktailSortBound    ldr x0,qAdrTableNumber                         // address number table    bl displayTable     ldr x0,qAdrTableNumber                         // address number table    mov x1,NBELEMENTS                              // number of élements     bl isSorted                                    // control sort    cmp x0,1                                       // sorted ?    beq 1f                                        ldr x0,qAdrszMessSortNok                       // no !! error sort    bl affichageMess    b 100f1:                                                 // yes    ldr x0,qAdrszMessSortOk    bl affichageMess100:                                               // standard end of the program     mov x0,0                                       // return code    mov x8,EXIT                                    // request to exit program    svc 0                                          // perform the system call qAdrsZoneConv:            .quad sZoneConvqAdrszCarriageReturn:     .quad szCarriageReturnqAdrsMessResult:          .quad sMessResultqAdrTableNumber:          .quad TableNumberqAdrszMessSortOk:         .quad szMessSortOkqAdrszMessSortNok:        .quad szMessSortNok/******************************************************************//*     control sorted table                                   */ /******************************************************************//* x0 contains the address of table *//* x1 contains the number of elements  > 0  *//* x0 return 0  if not sorted   1  if sorted */isSorted:    stp x2,lr,[sp,-16]!              // save  registers    stp x3,x4,[sp,-16]!              // save  registers    mov x2,0    ldr x4,[x0,x2,lsl 3]1:    add x2,x2,1    cmp x2,x1    bge 99f    ldr x3,[x0,x2, lsl 3]    cmp x3,x4    blt 98f    mov x4,x3    b 1b98:    mov x0,0                       // not sorted    b 100f99:    mov x0,1                       // sorted100:    ldp x3,x4,[sp],16              // restaur  2 registers    ldp x2,lr,[sp],16              // restaur  2 registers    ret                            // return to address lr x30/******************************************************************//*         cocktail sort  Bound                                            */ /******************************************************************//* x0 contains the address of table *//* x1 contains the first element    *//* x2 contains the number of element */cocktailSortBound:    stp x1,lr,[sp,-16]!        // save  registers    stp x2,x3,[sp,-16]!        // save  registers    stp x4,x5,[sp,-16]!        // save  registers    stp x6,x7,[sp,-16]!        // save  registers    stp x8,x9,[sp,-16]!        // save  registers    sub x2,x2,2                // compute endidx = n - 2                               // and r1 = beginidx1:                             // start loop 1    cmp x1,x2    bgt 100f    mov x8,x1                  // newbeginidx    mov x7,x2                  // newendidx    mov x3,x1                  // start index 2:                             // start loop 2    add x4,x3,1    ldr x5,[x0,x3,lsl 3]       // load value A[j]    ldr x6,[x0,x4,lsl 3]       // load value A[j+1]    cmp x6,x5                  // compare value    bge 3f     str x6,[x0,x3,lsl 3]       // if smaller inversion    str x5,[x0,x4,lsl 3]     mov x7,x3                   // and mov indice to newendidx3:    add x3,x3,1                // increment index j    cmp x3,x2                  // end ?    ble 2b                     // no -> loop 2    sub x2,x7,1                // endidx = newendidx - 1     bl displayTable    mov x3,x2                  // indice4:    add x4,x3,1    ldr x5,[x0,x3,lsl 3]       // load value A[j]    ldr x6,[x0,x4,lsl 3]       // load value A[j+1]    cmp x6,x5                  // compare value    bge 5f     str x6,[x0,x3,lsl 3]       // if smaller inversion    str x5,[x0,x4,lsl 3]     mov x8,x3                  // newbeginidx = indice5:    sub x3,x3,1                // decrement index j    cmp x3,x1                  // end ?    bge 4b                     // no -> loop 2     add x1,x8,1                // beginidx = newbeginidx    b 1b                       // loop 1 100:    ldp x8,x9,[sp],16          // restaur  2 registers    ldp x6,x7,[sp],16          // restaur  2 registers    ldp x4,x5,[sp],16          // restaur  2 registers    ldp x2,x3,[sp],16          // restaur  2 registers    ldp x1,lr,[sp],16          // restaur  2 registers    ret                        // return to address lr x30 /******************************************************************//*      Display table elements                                */ /******************************************************************//* x0 contains the address of table */displayTable:    stp x1,lr,[sp,-16]!              // save  registers    stp x2,x3,[sp,-16]!              // save  registers    mov x2,x0                        // table address    mov x3,01:                                   // loop display table    ldr x0,[x2,x3,lsl 3]    ldr x1,qAdrsZoneConv    bl conversion10S                  // décimal conversion    ldr x0,qAdrsMessResult    ldr x1,qAdrsZoneConv    bl strInsertAtCharInc            // insert result at @ character    bl affichageMess                 // display message    add x3,x3,1    cmp x3,NBELEMENTS - 1    ble 1b    ldr x0,qAdrszCarriageReturn    bl affichageMess    mov x0,x2                       // table address100:    ldp x2,x3,[sp],16               // restaur  2 registers    ldp x1,lr,[sp],16               // restaur  2 registers    ret                             // return to address lr x30/********************************************************//*        File Include fonctions                        *//********************************************************//* for this file see task include a file in language AArch64 assembly */.include "../includeARM64.inc" `

## ALGOL 60

Works with: A60
`begin    comment Sorting algorithms/Cocktail sort with shifting bounds - Algol 60;    integer nA;    nA:=20;     begin        integer array A[1:nA];          procedure cocktailsort(lb,ub);        value lb,ub; integer lb,ub;        begin            integer i,lbx,ubx;            boolean swapped;            lbx:=lb; ubx:=ub-1; swapped :=true;            for i:=1 while swapped do begin                 procedure swap(i); value i; integer i;                begin                    integer temp;                    temp  :=A[i];                    A[i]  :=A[i+1];                    A[i+1]:=temp;                    swapped:=true                end swap;                 swapped:=false;                for i:=lbx step  1 until ubx do if A[i]>A[i+1] then swap(i);                if swapped                then begin                    for i:=ubx step -1 until lbx do if A[i]>A[i+1] then swap(i);                    ubx:=ubx-1; lbx:=lbx+1                end            end        end cocktailsort;         procedure inittable(lb,ub);        value lb,ub; integer lb,ub;        begin            integer i;            for i:=lb step 1 until ub do A[i]:=entier(rand*100)        end inittable;         procedure writetable(lb,ub);        value lb,ub; integer lb,ub;        begin            integer i;            for i:=lb step 1 until ub do outinteger(1,A[i]);            outstring(1,"\n")        end writetable;         nA:=20;        inittable(1,nA);        writetable(1,nA);        cocktailsort(1,nA);        writetable(1,nA)    end end `
Output:
``` 6  92  61  64  73  3  81  28  62  67  83  33  77  14  16  23  47  19  33  78
3  6  14  16  19  23  28  33  33  47  61  62  64  67  73  77  78  81  83  92
```

## ARM Assembly

Works with: as version Raspberry Pi
` /* ARM assembly Raspberry PI  *//*  program cocktailSortBound.s  */  /* REMARK 1 : this program use routines in a include file    see task Include a file language arm assembly    for the routine affichageMess conversion10    see at end of this program the instruction include *//* for constantes see task include a file in arm assembly *//************************************//* Constantes                       *//************************************/.include "../constantes.inc" /*********************************//* Initialized data              *//*********************************/.dataszMessSortOk:       .asciz "Table sorted.\n"szMessSortNok:      .asciz "Table not sorted !!!!!.\n"sMessResult:        .asciz "Value  : @ \n"szCarriageReturn:   .asciz "\n" .align 4TableNumber:      .int   1,3,6,2,5,9,10,8,4,7#TableNumber:       .int   10,9,8,7,6,-5,4,3,2,1                   .equ NBELEMENTS, (. - TableNumber) / 4/*********************************//* UnInitialized data            *//*********************************/.bsssZoneConv:            .skip 24/*********************************//*  code section                 *//*********************************/.text.global main main:                                              @ entry of program  1:    ldr r0,iAdrTableNumber                         @ address number table    mov r1,#0    mov r2,#NBELEMENTS                             @ number of élements     bl cocktailSortBound    ldr r0,iAdrTableNumber                         @ address number table    bl displayTable     ldr r0,iAdrTableNumber                         @ address number table    mov r1,#NBELEMENTS                             @ number of élements     bl isSorted                                    @ control sort    cmp r0,#1                                      @ sorted ?    beq 2f                                        ldr r0,iAdrszMessSortNok                       @ no !! error sort    bl affichageMess    b 100f2:                                                 @ yes    ldr r0,iAdrszMessSortOk    bl affichageMess100:                                               @ standard end of the program     mov r0, #0                                     @ return code    mov r7, #EXIT                                  @ request to exit program    svc #0                                         @ perform the system call iAdrszCarriageReturn:     .int szCarriageReturniAdrsMessResult:          .int sMessResultiAdrTableNumber:          .int TableNumberiAdrszMessSortOk:         .int szMessSortOkiAdrszMessSortNok:        .int szMessSortNok/******************************************************************//*     control sorted table                                   */ /******************************************************************//* r0 contains the address of table *//* r1 contains the number of elements  > 0  *//* r0 return 0  if not sorted   1  if sorted */isSorted:    push {r2-r4,lr}                                    @ save registers    mov r2,#0    ldr r4,[r0,r2,lsl #2]1:    add r2,#1    cmp r2,r1    movge r0,#1    bge 100f    ldr r3,[r0,r2, lsl #2]    cmp r3,r4    movlt r0,#0    blt 100f    mov r4,r3    b 1b100:    pop {r2-r4,lr}    bx lr                                              @ return /******************************************************************//*         cocktail Sort                                          */ /******************************************************************//* r0 contains the address of table *//* r1 contains the first element    *//* r2 contains the number of element */cocktailSortBound:    push {r1-r9,lr}           @ save registers    sub r2,r2,#2              @ compute endidx = n - 2                              @ and r1= beginidx1:                            @ start loop 1    cmp r1,r2                 @ compare endidx beginidx    bgt 100f    mov r8,r1                 @ newbeginidx     mov r7,r2                 @ newendidx    mov r3,r1                 @ indice2:                            @ start loop 2    add r4,r3,#1    ldr r5,[r0,r3,lsl #2]     @ load value A[j]    ldr r6,[r0,r4,lsl #2]     @ load value A[j+1]    cmp r6,r5                 @ compare value    strlt r6,[r0,r3,lsl #2]   @ if smaller inversion    strlt r5,[r0,r4,lsl #2]     movlt r7,r3               @ and mov indice to newendidx    add r3,#1                 @ increment indice    cmp r3,r2                 @ end ?    ble 2b                    @ no -> loop 2     sub r2,r7,#1              @ endidx = newendidx     //bl displayTable    mov r3,r2                 @ indice3:    add r4,r3,#1    ldr r5,[r0,r3,lsl #2]     @ load value A[j]    ldr r6,[r0,r4,lsl #2]     @ load value A[j+1]    cmp r6,r5                 @ compare value    strlt r6,[r0,r3,lsl #2]   @ if smaller inversion    strlt r5,[r0,r4,lsl #2]     movlt r8,r3               @ newbeginidx = indice    sub r3,#1                 @ decrement indice    cmp r3,r1                 @ end ?    bge 3b                    @ no -> loop 3     //bl displayTable    add r1,r8,#1              @ beginidx = newbeginidx + 1    b 1b                       @ loop 1 100:    pop {r1-r9,lr}    bx lr                                                  @ return  /******************************************************************//*      Display table elements                                */ /******************************************************************//* r0 contains the address of table */displayTable:    push {r0-r3,lr}                                    @ save registers    mov r2,r0                                          @ table address    mov r3,#01:                                                     @ loop display table    ldr r0,[r2,r3,lsl #2]    ldr r1,iAdrsZoneConv                               @     bl conversion10S                                    @ décimal conversion     ldr r0,iAdrsMessResult    ldr r1,iAdrsZoneConv                               @ insert conversion    bl strInsertAtCharInc    bl affichageMess                                   @ display message    add r3,#1    cmp r3,#NBELEMENTS - 1    ble 1b    ldr r0,iAdrszCarriageReturn    bl affichageMess100:    pop {r0-r3,lr}    bx lriAdrsZoneConv:           .int sZoneConv/***************************************************//*      ROUTINES INCLUDE                           *//***************************************************/.include "../affichage.inc"  `

## Arturo

`cocktailShiftSort: function [items][    a: new items    beginIdx: 0    endIdx: (size a)-2     while [beginIdx =< endIdx][        newBeginIdx: endIdx        newEndIdx: beginIdx         loop beginIdx..endIdx 'i [            if a\[i] > a\[i+1] [                tmp: a\[i]                a\[i]: a\[i+1]                a\[i+1]: tmp                newEndIdx: i            ]        ]         endIdx: newEndIdx - 1         loop endIdx..beginIdx 'i [            if a\[i] > a\[i+1] [                tmp: a\[i]                a\[i]: a\[i+1]                a\[i+1]: tmp                newBeginIdx: i            ]        ]         beginIdx: newBeginIdx - 1    ]    return a] print cocktailShiftSort [3 1 2 8 5 7 9 4 6]`
Output:
`1 2 3 4 5 6 7 8 9`

## AutoHotkey

`cocktailShakerSort(A){    beginIdx := 1    endIdx := A.Count() - 1    while (beginIdx <= endIdx) {        newBeginIdx := endIdx        newEndIdx := beginIdx        ii := beginIdx        while (ii <= endIdx) {            if (A[ii] > A[ii + 1]) {                tempVal := A[ii], A[ii] := A[ii+1], A[ii+1] := tempVal                newEndIdx := ii            }            ii++        }        endIdx := newEndIdx - 1        ii := endIdx        while (ii >= beginIdx) {            if (A[ii] > A[ii + 1]) {                tempVal := A[ii], A[ii] := A[ii+1], A[ii+1] := tempVal                newBeginIdx := ii            }            ii--        }        beginIdx := newBeginIdx + 1    }}`
Examples:
`A := [8,6,4,3,5,2,7,1]cocktailShakerSort(A)for k, v in A    output .= v ", "MsgBox % "[" Trim(output, ", ") "]"     ; show output`
Output:
`[1, 2, 3, 4, 5, 6, 7, 8]`

## C

`#include <stdio.h>#include <string.h> void swap(char* p1, char* p2, size_t size) {    for (; size-- > 0; ++p1, ++p2) {        char tmp = *p1;        *p1 = *p2;        *p2 = tmp;    }} void cocktail_shaker_sort(void* base, size_t count, size_t size,                          int (*cmp)(const void*, const void*)) {    char* begin = base;    char* end = base + size * count;    if (end == begin)        return;    for (end -= size; begin < end; ) {        char* new_begin = end;        char* new_end = begin;        for (char* p = begin; p < end; p += size) {            char* q = p + size;            if (cmp(p, q) > 0) {                swap(p, q, size);                new_end = p;            }        }        end = new_end;        for (char* p = end; p > begin; p -= size) {            char* q = p - size;            if (cmp(q, p) > 0) {                swap(p, q, size);                new_begin = p;            }        }        begin = new_begin;    }} int string_compare(const void* p1, const void* p2) {    const char* const* s1 = p1;    const char* const* s2 = p2;    return strcmp(*s1, *s2);} void print(const char** a, size_t len) {    for (size_t i = 0; i < len; ++i)        printf("%s ", a[i]);    printf("\n");} int main() {    const char* a[] = { "one", "two", "three", "four", "five",        "six", "seven", "eight" };    const size_t len = sizeof(a)/sizeof(a[0]);    printf("before: ");    print(a, len);    cocktail_shaker_sort(a, len, sizeof(char*), string_compare);    printf("after: ");    print(a, len);    return 0;}`
Output:
```before: one two three four five six seven eight
after: eight five four one seven six three two
```

## C++

`#include <algorithm>#include <cassert>#include <iostream>#include <iterator>#include <vector> // This only works for random access iteratorstemplate <typename iterator>void cocktail_shaker_sort(iterator begin, iterator end) {    if (begin == end)        return;    for (--end; begin < end; ) {        iterator new_begin = end;        iterator new_end = begin;        for (iterator i = begin; i < end; ++i) {            iterator j = i + 1;            if (*j < *i) {                std::iter_swap(i, j);                new_end = i;            }        }        end = new_end;        for (iterator i = end; i > begin; --i) {            iterator j = i - 1;            if (*i < *j) {                std::iter_swap(i, j);                new_begin = i;            }        }        begin = new_begin;    }} template <typename iterator>void print(iterator begin, iterator end) {    if (begin == end)        return;    std::cout << *begin++;    while (begin != end)        std::cout << ' ' << *begin++;    std::cout << '\n';} int main() {    std::vector<int> v{5, 1, -6, 12, 3, 13, 2, 4, 0, 15};    std::cout << "before: ";    print(v.begin(), v.end());    cocktail_shaker_sort(v.begin(), v.end());    assert(std::is_sorted(v.begin(), v.end()));    std::cout << "after: ";    print(v.begin(), v.end());    return 0;}`
Output:
```before: 5 1 -6 12 3 13 2 4 0 15
after: -6 0 1 2 3 4 5 12 13 15
```

## FreeBASIC

Translation of: VBA
` Sub cocktailShakerSort(bs() As Long)    Dim As Long i, lb = Lbound(bs), ub = Ubound(bs) -1    Dim As Long newlb, newub, tmp     Do While lb <= ub        newlb = ub        newub = lb        For i = lb To ub            If bs(i) > bs(i + 1) Then                tmp = bs(i): bs(i) = bs(i + 1): bs(i + 1) = tmp                newub = i            End If        Next i        ub = newub - 1        For i = ub To lb Step -1            If bs(i) > bs(i + 1) Then                tmp = bs(i): bs(i) = bs(i + 1): bs(i + 1) = tmp                newlb = i            End If        Next i        lb = newlb + 1    LoopEnd Sub '--- Programa Principal --- Dim As Long i, array(-7 To 7)Dim As Long a = Lbound(array), b = Ubound(array) Randomize TimerFor i = a To b : array(i) = i : Next iFor i = a To b    Swap array(i), array(Int(Rnd * (b - a + 1)) + a)Next i Print "unsort ";For i = a To b : Print Using "####"; array(i); : Next i cocktailShakerSort(array())  ' ordenar el array Print !"\n  sort ";For i = a To b : Print Using "####"; array(i); : Next i Print !"\n--- terminado, pulsa RETURN---"Sleep `
Output:
```unsort   -4   0   5  -7  -2   4   3  -5  -1   7   2   1   6  -3  -6
sort   -7  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5   6   7
```

## Go

If you run this a few times, the figures for 8K random numbers upwards are quite stable at around the levels shown.

`package main import (    "fmt"    "math/rand"    "time") // translation of pseudo-codefunc cocktailShakerSort(a []int) {    var begin = 0    var end = len(a) - 2    for begin <= end {        newBegin := end        newEnd := begin        for i := begin; i <= end; i++ {            if a[i] > a[i+1] {                a[i+1], a[i] = a[i], a[i+1]                newEnd = i            }        }        end = newEnd - 1        for i := end; i >= begin; i-- {            if a[i] > a[i+1] {                a[i+1], a[i] = a[i], a[i+1]                newBegin = i            }        }        begin = newBegin + 1    }} // from the RC Cocktail sort task (no optimizations)func cocktailSort(a []int) {    last := len(a) - 1    for {        swapped := false        for i := 0; i < last; i++ {            if a[i] > a[i+1] {                a[i], a[i+1] = a[i+1], a[i]                swapped = true            }        }        if !swapped {            return        }        swapped = false        for i := last - 1; i >= 0; i-- {            if a[i] > a[i+1] {                a[i], a[i+1] = a[i+1], a[i]                swapped = true            }        }        if !swapped {            return        }    }} func main() {    // First make sure the routines are working correctly.    a := []int{21, 4, -9, 62, -7, 107, -62, 4, 0, -170}    fmt.Println("Original array:", a)    b := make([]int, len(a))    copy(b, a) // as sorts mutate array in place    cocktailSort(a)    fmt.Println("Cocktail sort :", a)    cocktailShakerSort(b)    fmt.Println("C/Shaker sort :", b)     // timing comparison code    rand.Seed(time.Now().UnixNano())    fmt.Println("\nRelative speed of the two sorts")    fmt.Println("  N    x faster (CSS v CS)")    fmt.Println("-----  -------------------")    const runs = 10 // average over 10 runs say    for _, n := range []int{1000, 2000, 4000, 8000, 10000, 20000} {        sum := 0.0        for i := 1; i <= runs; i++ {            // get 'n' random numbers in range [0, 100,000]            // with every other number being negated            nums := make([]int, n)            for i := 0; i < n; i++ {                rn := rand.Intn(100000)                if i%2 == 1 {                    rn = -rn                }                nums[i] = rn            }            // copy the array            nums2 := make([]int, n)            copy(nums2, nums)             start := time.Now()            cocktailSort(nums)            elapsed := time.Since(start)            start2 := time.Now()            cocktailShakerSort(nums2)            elapsed2 := time.Since(start2)            sum += float64(elapsed) / float64(elapsed2)        }        fmt.Printf(" %2dk      %0.3f\n", n/1000, sum/runs)    }}`
Output:

Sample run:

```Original array: [21 4 -9 62 -7 107 -62 4 0 -170]
Cocktail sort : [-170 -62 -9 -7 0 4 4 21 62 107]
C/Shaker sort : [-170 -62 -9 -7 0 4 4 21 62 107]

Relative speed of the two sorts
N    x faster (CSS v CS)
-----  -------------------
1k      1.439
2k      1.480
4k      1.415
8k      1.330
10k      1.326
20k      1.302
```

## Groovy

Translation of: Java
`class CocktailSort {    static void main(String[] args) {        Integer[] array = [ 5, 1, -6, 12, 3, 13, 2, 4, 0, 15 ]        println("before: " + Arrays.toString(array))        cocktailSort(array)        println("after: " + Arrays.toString(array))    }     // Sorts an array of elements that implement the Comparable interface    static void cocktailSort(Object[] array) {        int begin = 0        int end = array.length        if (end == 0) {            return        }        for (--end; begin < end; ) {            int new_begin = end            int new_end = begin            for (int i = begin; i < end; ++i) {                Comparable c1 = (Comparable)array[i]                Comparable c2 = (Comparable)array[i + 1]                if (c1 > c2) {                    swap(array, i, i + 1)                    new_end = i                }            }            end = new_end            for (int i = end; i > begin; --i) {                Comparable c1 = (Comparable)array[i - 1]                Comparable c2 = (Comparable)array[i]                if (c1 > c2) {                    swap(array, i, i - 1)                    new_begin = i                }            }            begin = new_begin        }    }     private static void swap(Object[] array, int i, int j) {        Object tmp = array[i]        array[i] = array[j]        array[j] = tmp    }}`
Output:
```before: [5, 1, -6, 12, 3, 13, 2, 4, 0, 15]
after: [-6, 0, 1, 2, 3, 4, 5, 12, 13, 15]```

## Java

`import java.util.*; public class CocktailSort {    public static void main(String[] args) {        Integer[] array = new Integer[]{ 5, 1, -6, 12, 3, 13, 2, 4, 0, 15 };        System.out.println("before: " + Arrays.toString(array));        cocktailSort(array);        System.out.println("after: " + Arrays.toString(array));    }     // Sorts an array of elements that implement the Comparable interface    public static void cocktailSort(Object[] array) {        int begin = 0;        int end = array.length;        if (end == 0)            return;        for (--end; begin < end; ) {            int new_begin = end;            int new_end = begin;            for (int i = begin; i < end; ++i) {                Comparable c1 = (Comparable)array[i];                Comparable c2 = (Comparable)array[i + 1];                if (c1.compareTo(c2) > 0) {                    swap(array, i, i + 1);                    new_end = i;                }            }            end = new_end;            for (int i = end; i > begin; --i) {                Comparable c1 = (Comparable)array[i - 1];                Comparable c2 = (Comparable)array[i];                if (c1.compareTo(c2) > 0) {                    swap(array, i, i - 1);                    new_begin = i;                }            }            begin = new_begin;        }    }     private static void swap(Object[] array, int i, int j) {        Object tmp = array[i];        array[i] = array[j];        array[j] = tmp;    }}`
Output:
```before: [5, 1, -6, 12, 3, 13, 2, 4, 0, 15]
after: [-6, 0, 1, 2, 3, 4, 5, 12, 13, 15]
```

## Julia

The implementation chosen is to extend the native Julia base sort! function, which by default in base Julia supports insertion sort, quick sort, partial quick sort, and merge sort.

`module CocktailShakerSorts using Base.Order, Base.Sortimport Base.Sort: sort!export CocktailShakerSort struct CocktailSortAlg <: Algorithm endconst CocktailShakerSort = CocktailSortAlg() function sort!(A::AbstractVector, lo::Int, hi::Int, a::CocktailSortAlg, ord::Ordering)    if lo > 1 || hi < length(A)        return sort!(view(A, lo:hi), 1, length(A), a, ord)    end    forward, beginindex, endindex = ord isa ForwardOrdering, 1, length(A) - 1     while beginindex <= endindex		newbegin, newend = endindex, beginindex        for idx in beginindex:endindex            if (forward && A[idx] > A[idx + 1]) || (!forward && A[idx] < A[idx + 1])                A[idx + 1], A[idx] = A[idx], A[idx + 1]                newend = idx            end        end        # end has another in correct place, so narrow end by 1        endindex = newend - 1         for idx in endindex:-1:beginindex            if (forward && A[idx] > A[idx + 1]) || (!forward && A[idx] < A[idx + 1])                A[idx + 1], A[idx] = A[idx], A[idx + 1]                newbegin = idx            end        end        # beginning has another in correct place, so narrow beginning by 1        beginindex = newbegin + 1    end    Aend end # module using .CocktailShakerSortsusing BenchmarkTools cocktailshakersort!(v) = sort!(v; alg=CocktailShakerSort) arr = [5, 8, 2, 0, 6, 1, 9, 3, 4]println(arr, " => ", sort(arr, alg=CocktailShakerSort), " => ",    sort(arr, alg=CocktailShakerSort, rev=true)) println("\nUsing default sort, which is Quicksort with integers:")@btime sort!([5, 8, 2, 0, 6, 1, 9, 3, 4])println("\nUsing CocktailShakerSort:")@btime cocktailshakersort!([5, 8, 2, 0, 6, 1, 9, 3, 4]) `
Output:
```[5, 8, 2, 0, 6, 1, 9, 3, 4] => [0, 1, 2, 3, 4, 5, 6, 8, 9] => [9, 8, 6, 5, 4, 3, 2, 1, 0]

Using default sort, which is Quicksort with integers:
56.765 ns (1 allocation: 160 bytes)

Using CocktailShakerSort:
94.443 ns (1 allocation: 160 bytes)
```

## Kotlin

Translation of: Java
`fun <T> swap(array: Array<T>, i: Int, j: Int) {    val temp = array[i]    array[i] = array[j]    array[j] = temp} fun <T> cocktailSort(array: Array<T>) where T : Comparable<T> {    var begin = 0    var end = array.size    if (end == 0) {        return    }    --end    while (begin < end) {        var newBegin = end        var newEnd = begin        for (i in begin until end) {            val c1 = array[i]            val c2 = array[i + 1]            if (c1 > c2) {                swap(array, i, i + 1)                newEnd = i            }        }        end = newEnd        for (i in end downTo begin + 1) {            val c1 = array[i - 1]            val c2 = array[i]            if (c1 > c2) {                swap(array, i, i - 1)                newBegin = i            }        }        begin = newBegin    }} fun main() {    val array: Array<Int> = intArrayOf(5, 1, -6, 12, 3, 13, 2, 4, 0, 15).toList().toTypedArray()     println("before: \${array.contentToString()}")    cocktailSort(array)    println("after: \${array.contentToString()}")}`
Output:
```before: [5, 1, -6, 12, 3, 13, 2, 4, 0, 15]
after: [-6, 0, 1, 2, 3, 4, 5, 12, 13, 15]```

## Mathematica/Wolfram Language

`ClearAll[CocktailShakerSort]CocktailShakerSort[in_List] :=  Module[{x = in, swapped, begin = 1, end = Length[in] - 1},  swapped = True;  While[swapped,   swapped = False;   Do[    If[x[[i]] > x[[i + 1]],     x[[{i, i + 1}]] //= Reverse;     swapped = True;     ]    ,    {i, begin, end}    ];   end--;    Do[    If[x[[i]] > x[[i + 1]],     x[[{i, i + 1}]] //= Reverse;     swapped = True;     ]    ,    {i, end, begin, -1}    ];   begin++;   ];  x ]CocktailShakerSort[{44, 21, 5, 88, 52, 44, 36, 93, 66, 18, 88, 61, 45, 47, 47, 68, 19, 60}]`
Output:
`{5, 18, 19, 21, 36, 44, 44, 45, 47, 47, 52, 60, 61, 66, 68, 88, 88, 93}`

## Nim

`proc cocktailShakerSort[T](a: var openarray[T]) =   var beginIdx = 0  var endIdx = a.len - 2   while beginIdx <= endIdx:    var newBeginIdx = endIdx    var newEndIdx = beginIdx    for i in beginIdx..endIdx:      if a[i] > a[i + 1]:        swap a[i], a[i + 1]        newEndIdx = i     endIdx = newEndIdx - 1     for i in countdown(endIdx, beginIdx):      if a[i] > a[i + 1]:        swap a[i], a[i + 1]        newBeginIdx = i     beginIdx = newBeginIdx + 1 var a = @[4, 65, 2, -31, 0, 99, 2, 83, 782]cocktailShakerSort aecho a`
Output:
`@[-31, 0, 2, 2, 4, 65, 83, 99, 782]`

## Perl

`use strict;use warnings;use feature 'say'; sub cocktail_sort {    my @a = @_;    my (\$min, \$max) = (0, \$#a-1);    while (1) {        my \$swapped_forward = 0;        for my \$i (\$min .. \$max) {            if (\$a[\$i] gt \$a[\$i+1]) {                @a[\$i, \$i+1] = @a[\$i+1, \$i];                \$swapped_forward = 1            }        }        last if not \$swapped_forward;        \$max -= 1;         my \$swapped_backward = 0;        for my \$i (reverse \$min .. \$max) {            if (\$a[\$i] gt \$a[\$i+1]) {                @a[\$i, \$i+1] = @a[\$i+1, \$i];                \$swapped_backward = 1;            }        }        last if not \$swapped_backward;        \$min += 1;    }    @a} say join ' ', cocktail_sort( <t h e q u i c k b r o w n f o x j u m p s o v e r t h e l a z y d o g> );`
Output:
`a b c d e e e f g h h i j k l m n o o o o p q r r s t t u u v w x y z`

## Phix

Averages 7 or 8% better than Sorting_algorithms/Cocktail_sort#Phix which already shifted the bounds, however this shifts >1 (sometimes).

```with javascript_semantics

function cocktailShakerSort(sequence s)
s = deep_copy(s)
integer beginIdx = 1,
endIdx = length(s)-1
while beginIdx <= endIdx do
integer newBeginIdx = endIdx,
newEndIdx = beginIdx
for ii=beginIdx to endIdx do
object si = s[ii],
sn = s[ii+1]
if si>sn then
s[ii] = sn
s[ii+1] = si
newEndIdx = ii
end if
end for
-- elements after `newEndIdx` are now in correct order
endIdx = newEndIdx - 1
for ii=endIdx to beginIdx by -1 do
object si = s[ii],
sn = s[ii+1]
if si>sn then
s[ii] = sn
s[ii+1] = si
newBeginIdx = ii
end if
end for
-- elements before `newBeginIdx` are now in correct order.
beginIdx = newBeginIdx + 1
end while
return s
end function
sequence s = shuffle(tagset(12))  ?{s,cocktailShakerSort(s)}
s = {"one","two","three","four"}  ?{s,cocktailShakerSort(s)}
```
Output:
```{{12,2,1,9,4,10,8,5,3,11,6,7},{1,2,3,4,5,6,7,8,9,10,11,12}}
{{"one","two","three","four"},{"four","one","three","two"}}
```

## Python

` """ Python example of http://rosettacode.org/wiki/Sorting_algorithms/Cocktail_sort_with_shifting_bounds based on  http://rosettacode.org/wiki/Sorting_algorithms/Cocktail_sort#Python """ def cocktailshiftingbounds(A):    beginIdx = 0    endIdx = len(A) - 1     while beginIdx <= endIdx:        newBeginIdx = endIdx        newEndIdx = beginIdx        for ii in range(beginIdx,endIdx):            if A[ii] > A[ii + 1]:                A[ii+1], A[ii] = A[ii], A[ii+1]                newEndIdx = ii         endIdx = newEndIdx         for ii in range(endIdx,beginIdx-1,-1):            if A[ii] > A[ii + 1]:                A[ii+1], A[ii] = A[ii], A[ii+1]                newBeginIdx = ii         beginIdx = newBeginIdx + 1 test1 = [7, 6, 5, 9, 8, 4, 3, 1, 2, 0]cocktailshiftingbounds(test1)print(test1) test2=list('big fjords vex quick waltz nymph')cocktailshiftingbounds(test2)print(''.join(test2)) `
Output:
```[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
abcdefghiijklmnopqrstuvwxyz
```

## Raku

Works with: Rakudo version 2020.05
`sub cocktail_sort ( @a ) {    my (\$min, \$max) = 0, +@a - 2;    loop {        my \$swapped_forward = 0;        for \$min .. \$max -> \$i {            given @a[\$i] cmp @a[\$i+1] {                when More {                    @a[ \$i, \$i+1 ] .= reverse;                    \$swapped_forward = 1                }                default {}            }        }        last if not \$swapped_forward;        \$max -= 1;         my \$swapped_backward = 0;        for (\$min .. \$max).reverse -> \$i {            given @a[\$i] cmp @a[\$i+1] {                when More {                    @a[ \$i, \$i+1 ] .= reverse;                    \$swapped_backward = 1                }                default {}            }        }        last if not \$swapped_backward;        \$min += 1;    }    @a} my @weights = (flat 0..9, 'A'..'F').roll(2 + ^4 .roll).join xx 100;say @weights.sort.Str eq @weights.&cocktail_sort.Str ?? 'ok' !! 'not ok';`

## REXX

This REXX version can handle array elements that may contain blanks or spaces.

`/*REXX program sorts an array using the   cocktail─sort   method  with shifting bounds. */call gen                                         /*generate some array elements.        */call show  'before sort'                         /*show  unsorted  array elements.      */     say copies('█', 101)                        /*show a separator line  (a fence).    */call cocktailSort  #                             /*invoke the cocktail sort subroutine. */call show  ' after sort'                         /*show    sorted  array elements.      */exit                                             /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/cocktailSort: procedure expose @.;    parse arg N             /*N:  is number of items. */                                      end\$= N - 1;     beg\$= 1                     do while beg\$ <= end\$                     beg\$\$= end\$;               end\$\$= beg\$                        do j=beg\$ to end\$;                   jp= j + 1                        if @.j>@.jp  then do;  [email protected].j;  @.[email protected].jp;  @.jp=_;  end\$\$=j;  end                        end   /*j*/                     end\$= end\$\$ - 1                        do k=end\$  to beg\$  by -1;           kp= k + 1                        if @.k>@.kp  then do;  [email protected].k;  @.[email protected].kp;  @.kp=_;  beg\$\$=k;  end                        end   /*k*/                     beg\$= beg\$\$ + 1                     end      /*while*/              return/*──────────────────────────────────────────────────────────────────────────────────────*/gen: @.=                                        /*assign a default value for the stem. */     @.1 = '---the 22 card tarot deck (larger deck has 56 additional cards in 4 suits)---'     @.2 = '==========symbol====================pip======================================'     @.3 = 'the juggler                  ◄───     I'     @.4 = 'the high priestess  [Popess] ◄───    II'     @.5 = 'the empress                  ◄───   III'     @.6 = 'the emperor                  ◄───    IV'     @.7 = 'the hierophant  [Pope]       ◄───     V'     @.8 = 'the lovers                   ◄───    VI'     @.9 = 'the chariot                  ◄───   VII'     @.10= 'justice                      ◄───  VIII'     @.11= 'the hermit                   ◄───    IX'     @.12= 'fortune  [the wheel of]      ◄───     X'     @.13= 'strength                     ◄───    XI'     @.14= 'the hanging man              ◄───   XII'     @.15= 'death  [often unlabeled]     ◄───  XIII'     @.16= 'temperance                   ◄───   XIV'     @.17= 'the devil                    ◄───    XV'     @.18= 'lightning  [the tower]       ◄───   XVI'     @.18= 'the stars                    ◄───  XVII'     @.20= 'the moon                     ◄─── XVIII'     @.21= 'the sun                      ◄───   XIX'     @.22= 'judgment                     ◄───    XX'     @.23= 'the world                    ◄───   XXI'     @.24= 'the fool  [often unnumbered] ◄───  XXII'             do #= 1  until @.#==''; end;  #= #-1 /*find how many entries in the array.  */     return                                      /* [↑]  adjust for DO loop advancement.*//*──────────────────────────────────────────────────────────────────────────────────────*/show: w= length(#);               do j=1  for #      /*#:  is the number of items in @. */                                  say 'element'    right(j, w)     arg(1)":"    @.j                                  end   /*j*/        /*     ↑                           */      return                                         /*     └─────max width of any line.*/`
output   when using the internal default inputs:

(Shown at three-quarter size.)

```element  1 before sort: ---the 22 card tarot deck (larger deck has 56 additional cards in 4 suits)---
element  2 before sort: ==========symbol====================pip======================================
element  3 before sort: the juggler                  ◄───     I
element  4 before sort: the high priestess  [Popess] ◄───    II
element  5 before sort: the empress                  ◄───   III
element  6 before sort: the emperor                  ◄───    IV
element  7 before sort: the hierophant  [Pope]       ◄───     V
element  8 before sort: the lovers                   ◄───    VI
element  9 before sort: the chariot                  ◄───   VII
element 10 before sort: justice                      ◄───  VIII
element 11 before sort: the hermit                   ◄───    IX
element 12 before sort: fortune  [the wheel of]      ◄───     X
element 13 before sort: strength                     ◄───    XI
element 14 before sort: the hanging man              ◄───   XII
element 15 before sort: death  [often unlabeled]     ◄───  XIII
element 16 before sort: temperance                   ◄───   XIV
element 17 before sort: the devil                    ◄───    XV
element 18 before sort: the stars                    ◄───  XVII
█████████████████████████████████████████████████████████████████████████████████████████████████████
element  1  after sort: ---the 22 card tarot deck (larger deck has 56 additional cards in 4 suits)---
element  2  after sort: ==========symbol====================pip======================================
element  3  after sort: death  [often unlabeled]     ◄───  XIII
element  4  after sort: fortune  [the wheel of]      ◄───     X
element  5  after sort: justice                      ◄───  VIII
element  6  after sort: strength                     ◄───    XI
element  7  after sort: temperance                   ◄───   XIV
element  8  after sort: the chariot                  ◄───   VII
element  9  after sort: the devil                    ◄───    XV
element 10  after sort: the emperor                  ◄───    IV
element 11  after sort: the empress                  ◄───   III
element 12  after sort: the hanging man              ◄───   XII
element 13  after sort: the hermit                   ◄───    IX
element 14  after sort: the hierophant  [Pope]       ◄───     V
element 15  after sort: the high priestess  [Popess] ◄───    II
element 16  after sort: the juggler                  ◄───     I
element 17  after sort: the lovers                   ◄───    VI
element 18  after sort: the stars                    ◄───  XVII
```

## Rust

`fn cocktail_shaker_sort<T: PartialOrd>(a: &mut [T]) {    let mut begin = 0;    let mut end = a.len();    if end == 0 {        return;    }    end -= 1;    while begin < end {        let mut new_begin = end;        let mut new_end = begin;        for i in begin..end {            if a[i + 1] < a[i] {                a.swap(i, i + 1);                new_end = i;            }        }        end = new_end;        let mut i = end;        while i > begin {            if a[i] < a[i - 1] {                a.swap(i, i - 1);                new_begin = i;            }            i -= 1;        }        begin = new_begin;    }} fn main() {    let mut v = vec![5, 1, -6, 12, 3, 13, 2, 4, 0, 15];    println!("before: {:?}", v);    cocktail_shaker_sort(&mut v);    println!("after:  {:?}", v);}`
Output:
```before: [5, 1, -6, 12, 3, 13, 2, 4, 0, 15]
after:  [-6, 0, 1, 2, 3, 4, 5, 12, 13, 15]
```

## Swift

Translation of: Rust
`func cocktailShakerSort<T: Comparable>(_ a: inout [T]) {    var begin = 0    var end = a.count    if end == 0 {        return    }    end -= 1    while begin < end {        var new_begin = end        var new_end = begin        var i = begin        while i < end {            if a[i + 1] < a[i] {                a.swapAt(i, i + 1)                new_end = i            }            i += 1        }        end = new_end        i = end        while i > begin {            if a[i] < a[i - 1] {                a.swapAt(i, i - 1)                new_begin = i            }            i -= 1        }        begin = new_begin    }} var array = [5, 1, -6, 12, 3, 13, 2, 4, 0, 15]print("before: \(array)")cocktailShakerSort(&array)print(" after: \(array)") var array2 = ["one", "two", "three", "four", "five", "six", "seven", "eight"]print("before: \(array2)")cocktailShakerSort(&array2)print(" after: \(array2)")`
Output:
```before: [5, 1, -6, 12, 3, 13, 2, 4, 0, 15]
after: [-6, 0, 1, 2, 3, 4, 5, 12, 13, 15]
before: ["one", "two", "three", "four", "five", "six", "seven", "eight"]
after: ["eight", "five", "four", "one", "seven", "six", "three", "two"]
```

## VBA

`' Sorting algorithms/Cocktail sort with shifting bounds - VBAFunction cocktailShakerSort(ByVal A As Variant) As Variant    beginIdx = LBound(A)    endIdx = UBound(A) - 1    Do While beginIdx <= endIdx        newBeginIdx = endIdx        newEndIdx = beginIdx        For ii = beginIdx To endIdx            If A(ii) > A(ii + 1) Then                tmp = A(ii): A(ii) = A(ii + 1): A(ii + 1) = tmp                newEndIdx = ii            End If        Next ii        endIdx = newEndIdx - 1        For ii = endIdx To beginIdx Step -1            If A(ii) > A(ii + 1) Then                tmp = A(ii): A(ii) = A(ii + 1): A(ii + 1) = tmp                newBeginIdx = ii            End If        Next ii        beginIdx = newBeginIdx + 1    Loop    cocktailShakerSort = AEnd Function 'cocktailShakerSortPublic Sub main()    Dim B(20) As Variant    For i = LBound(B) To UBound(B)        B(i) = Int(Rnd() * 100)    Next i    Debug.Print Join(B, ", ")    Debug.Print Join(cocktailShakerSort(B), ", ")End Sub`
Output:
```52, 76, 5, 59, 46, 29, 62, 64, 26, 27, 82, 82, 58, 98, 91, 22, 69, 98, 24, 53, 10
5, 10, 22, 24, 26, 27, 29, 46, 52, 53, 58, 59, 62, 64, 69, 76, 82, 82, 91, 98, 98
```

## VBScript

`' Sorting algorithms/Cocktail sort with shifting bounds - VBScriptFunction cocktailShakerSort(ByVal A)    beginIdx = Lbound(A)    endIdx = Ubound(A)-1    Do While beginIdx <= endIdx        newBeginIdx = endIdx        newEndIdx = beginIdx        For ii = beginIdx To endIdx            If A(ii) > A(ii+1) Then                tmp=A(ii) : A(ii)=A(ii+1) : A(ii+1)=tmp                newEndIdx = ii            End If        Next        endIdx = newEndIdx - 1        For ii = endIdx To beginIdx Step -1            If A(ii) > A(ii+1) Then                tmp=A(ii) : A(ii)=A(ii+1) : A(ii+1)=tmp                newBeginIdx = ii            End If        Next        beginIdx = newBeginIdx+1    Loop    cocktailShakerSort=AEnd Function 'cocktailShakerSortDim B(20)For i=Lbound(B) To Ubound(B)    B(i)=Int(Rnd()*100)NextWscript.Echo Join(cocktailShakerSort(B)," ") `
Output:
``` 1 4 5 28 30 36 37 41 53 57 70 70 76 77 79 81 86 87 94 96
```

## Visual Basic .NET

Works with: Visual Basic .NET version 9.0
`' Sorting algorithms/Cocktail sort with shifting bounds - VB.Net    Private Sub Cocktail_Shaker_Sort()        Dim A(20), tmp As Long  'or Integer Long Single Double String        Dim i, beginIdx, endIdx, newBeginIdx, newEndIdx As Integer        'Generate the list        For i = LBound(A) To UBound(A)            A(i) = Int(Rnd() * 100)        Next i        'Sort the list        beginIdx = LBound(A)        endIdx = UBound(A) - 1        Do While beginIdx <= endIdx            newBeginIdx = endIdx            newEndIdx = beginIdx            For ii = beginIdx To endIdx                If A(ii) > A(ii + 1) Then                    tmp = A(ii) : A(ii) = A(ii + 1) : A(ii + 1) = tmp                    newEndIdx = ii                End If            Next ii            endIdx = newEndIdx - 1            For ii = endIdx To beginIdx Step -1                If A(ii) > A(ii + 1) Then                    tmp = A(ii) : A(ii) = A(ii + 1) : A(ii + 1) = tmp                    newBeginIdx = ii                End If            Next ii            beginIdx = newBeginIdx + 1        Loop        'Display the sorted list        Debug.Print(String.Join(", ", A))    End Sub 'Cocktail_Shaker_Sort `
Output:
```1, 4, 5, 28, 30, 36, 37, 41, 52, 53, 57, 70, 70, 76, 77, 79, 81, 86, 87, 94, 96
```

## Wren

Translation of: Go
Library: Wren-fmt

Limited to 5 runs for each sample size as takes a few minutes to process.

Ratios are noticeably less than the Go example (more in keeping with the REXX results in the talk page) and vary more if the script is run a few times. Frankly, I don't know why this is.

`import "/fmt" for Fmtimport "random" for Random // translation of pseudo-codevar cocktailShakerSort = Fn.new { |a|    var begin = 0    var end = a.count - 2    while (begin <= end) {        var newBegin = end        var newEnd = begin        for (i in begin..end) {            if (a[i] > a[i+1]) {                var t = a[i+1]                a[i+1] = a[i]                a[i] = t                newEnd = i            }        }        end = newEnd - 1        if (end >= begin) {            for (i in end..begin) {                if (a[i] > a[i+1]) {                    var t = a[i+1]                    a[i+1] = a[i]                    a[i] = t                    newBegin = i                }            }        }        begin = newBegin + 1    }} // from the RC Cocktail sort task (no optimizations)var cocktailSort = Fn.new { |a|    var last = a.count - 1    while (true) {        var swapped = false        for (i in 0...last) {            if (a[i] > a[i+1]) {                var t = a[i]                a[i] = a[i+1]                a[i+1] = t                swapped = true            }        }        if (!swapped) return        swapped = false        if (last >= 1) {            for (i in last-1..0) {                if (a[i] > a[i+1]) {                    var t = a[i]                    a[i] = a[i+1]                    a[i+1] = t                    swapped = true                }            }        }         if (!swapped) return    }} // First make sure the routines are working correctly.var a = [21, 4, -9, 62, -7, 107, -62, 4, 0, -170]System.print("Original array: %(a)")var b = a.toList // make copy as sorts mutate array in placecocktailSort.call(a)System.print("Cocktail sort : %(a)")cocktailShakerSort.call(b)System.print("C/Shaker sort : %(b)") // timing comparison codevar rand = Random.new()System.print("\nRelative speed of the two sorts")System.print("  N    x faster (CSS v CS)")System.print("-----  -------------------")var runs = 5 // average over 5 runs sayfor (n in [1000, 2000, 4000, 8000, 10000, 20000]) {    var sum = 0    for (i in 1..runs) {        // get 'n' random numbers in range [0, 100,000]        // with every other number being negated        var nums = List.filled(n, 0)        for (i in 0...n) {            var rn = rand.int(100000)            if (i%2 == 1) rn = -rn            nums[i] = rn        }        // copy the array        var nums2 = nums.toList         var start = System.clock        cocktailSort.call(nums)        var elapsed = System.clock - start        var start2 = System.clock        cocktailShakerSort.call(nums2)        var elapsed2 = System.clock - start2        sum = sum + elapsed/elapsed2    }    System.print(" %(Fmt.d(2, (n/1000).floor))k      %(Fmt.f(0, sum/runs, 3))")}`
Output:

Sample run:

```Original array: [21, 4, -9, 62, -7, 107, -62, 4, 0, -170]
Cocktail sort : [-170, -62, -9, -7, 0, 4, 4, 21, 62, 107]
C/Shaker sort : [-170, -62, -9, -7, 0, 4, 4, 21, 62, 107]

Relative speed of the two sorts
N    x faster (CSS v CS)
-----  -------------------
1k      1.257
2k      1.223
4k      1.212
8k      1.216
10k      1.239
20k      1.228
```