     x 1 + x!
     p 0 <array> :> c 0 :> k! 0 :> r!
     p 1 - [| i |
-        i [ 0 ] [ 1 - c nth ] if-zero i c set-nth
+        i [ 0 ] [ 1 - c nth-unsafe ] if-zero i c set-nth-unsafe
         [ k x < ] [
-            i c [ 1 + ] change-nth
-            n i c nth - p i 1 + - nCk r!
+            i c [ 1 + ] change-nth-unsafe
+            n i c nth-unsafe - p i 1 + - nCk r!
             k r + k!
         ] do while k r - k!
     ] each-integer
-    p 2 < [ 0 ] [ p 2 - c nth ] if
-    p 1 < [ drop ] [ x + k - p 1 - c set-nth ] if
+    p 2 < [ 0 ] [ p 2 - c nth-unsafe ] if
+    p 1 < [ drop ] [ x + k - p 1 - c set-nth-unsafe ] if
     c [ 1 - ] map! ;
 
 PRIVATE>

<PRIVATE

: cut-point ( seq -- n )
    [ last ] keep [ [ > ] keep swap ] find-last drop nip ; inline

: greater-from-last ( n seq -- i )
    [ nip ] [ nth ] 2bi [ > ] curry find-last drop ; inline

: reverse-tail! ( n seq -- seq )
    [ swap 1 + tail-slice reverse! drop ] keep ; inline

: (next-permutation) ( seq -- seq )
    dup cut-point [
        swap [ greater-from-last ] 2keep
        [ exchange ] [ reverse-tail! nip ] 3bi
    ] [ reverse! ] if* ;

HINTS: (next-permutation) array ;


<PRIVATE

: <permutation-iota> ( seq -- <iota> )
    length factorial <iota> ; inline

: permutations-quot ( seq quot -- seq quot' )
    [ [ <permutation-iota> ] [ length <iota> >array ] [ ] tri ] dip
    '[ drop _ [ _ nths-unsafe @ ] keep next-permutation drop ] ; inline

PRIVATE>
