\ Combsort
\ Adapted from code by Wayne Conrad and Nick Estes

defer less

: newgap ( gap -- gap )
  10 13 */
  dup 9 11 within if
    drop 11
  then 1 max ;

: swap-by-pointer? ( p1 p2 -- flag )
  >r dup @ r@ @ less if
    r@ @ over @ r> ! swap ! -1 else
    r> 2drop 0 then ; 

: comb ( gap 0 array length -- flag )
  bounds ?do
    over i + i swap-by-pointer? or 
  1 cells +loop nip ;

: combsort ( array length -- ) 
  dup
  begin
    newgap dup >r cells
    0 2over r@ - cells comb
    r@ swap 0= r> 2 < and
  until
  drop 2drop ;

' < is less
10 Constant LENGTH
create array
1 , 6 , 5 , 3 , 8 , 9 , 7 , 2 , 4 , 0 ,

: .array ( array length -- )
  cells bounds ?do
    i @ .
  1 cells +loop ;

: main ( array length -- )
   2dup combsort
   .array
;

array 10 main

\ combsort with duplicates removed

defer less
defer equal

: newgap ( gap -- gap )
  10 13 */
  dup 9 11 within if
    drop 11
  then 1 max ;

: swap-by-pointer? ( p1 p2 -- 0 0 | -1 0 | p2 -1 )
  over @ over @ ( p1 p2 a b )
  2dup less if
    swap rot ! swap ! -1 0 else
    equal if nip -1 else 0 0 then
  then ;

: comb-and-remove ( gap 0 array length -- end-of-array flag )
  2>R begin
    over r'@ + r'@ swap-by-pointer? 
      if 
        dup cell+ swap r'@ over - move r'@ 1 cells - 2r> nip 2>r else
        or
      then 
    r> 1 cells + >R r@ r'@ u< 0= 
  until 2r> drop swap ;

: combsort ( array length -- ) 
  dup
  begin
    newgap dup >r cells
    0 2over r@ - cells comb
    2>r over r'@ - 1 cells / 
    r@ swap 0= r> 2 < and
  until
  drop 2drop ;