+: assoc-zip-with ( quot: ( key value -- calc ) -- alist )
+ '[ _ 2keep 2array swap ] assoc-map ; inline
+
+: take-while ( ... seq quot: ( ... elt -- ... ? ) -- head-slice )
+ [ '[ @ not ] find drop ] keepd swap
+ [ dup length ] unless* head-slice ; inline
+
+: drop-while ( ... seq quot: ( ... elt -- ... ? ) -- tail-slice )
+ [ '[ @ not ] find drop ] keepd swap
+ [ dup length ] unless* tail-slice ; inline
+
+: count-head ( seq quot -- n )
+ [ not ] compose [ find drop ] keepd length or ; inline
+
+: count-tail ( seq quot -- n )
+ [ not ] compose [ find-last drop ] keepd
+ length swap [ - 1 - ] when* ; inline
+
+:: shorten* ( vector n -- seq )
+ vector n tail
+ n vector shorten ;
+
+:: interleaved-as ( seq glue exemplar -- newseq )
+ seq length dup 1 - + 0 max exemplar new-sequence :> newseq
+ seq [ 2 * newseq set-nth-unsafe ] each-index
+ seq length 1 - [ 2 * 1 + glue swap newseq set-nth-unsafe ] each-integer
+ newseq ;
+
+: interleaved ( seq glue -- newseq )
+ over interleaved-as ;
+
+: extract! ( ... seq quot: ( ... elt -- ... ? ) -- ... seq )
+ [ dup ] compose over [ length ] keep new-resizable
+ [ [ push-if ] 2curry reject! ] keep swap like ; inline
+
+: find-pred-loop ( ... i n seq quot: ( ... elt -- ... calc ? ) -- ... calc/f i/f elt/f )
+ 2pick < [
+ [ nipd call ] 4keep
+ 3 7 0 nrotated
+ [ [ 3drop ] 2dip rot ]
+ [ 2drop [ 1 + ] 3dip find-pred-loop ] if
+ ] [
+ 4drop f f f
+ ] if ; inline recursive
+
+: find-pred ( ... seq quot: ( ... elt -- ... calc ) pred: ( ... calc -- ... ? ) -- ... calc/f i/f elt/f )
+ [ 0 ] 3dip
+ [ [ length check-length ] keep ] 2dip
+ '[ nth-unsafe _ keep swap _ keep swap ] find-pred-loop swapd ; inline
+
+! https://en.wikipedia.org/wiki/Maximum_subarray_problem
+! Kadane's algorithm O(n) largest sum in subarray
+: max-subarray-sum ( seq -- sum )
+ [ -1/0. 0 ] dip
+ [ [ + ] keep max [ max ] keep ] each drop ;
+
+TUPLE: step-slice
+ { from integer read-only initial: 0 }
+ { to integer read-only initial: 0 }
+ { seq read-only }
+ { step integer read-only } ;
+
+:: <step-slice> ( from to step seq -- step-slice )
+ step zero? [ "can't be zero" throw ] when
+ seq length :> len
+ step 0 > [
+ from [ 0 ] unless*
+ to [ len ] unless*
+ ] [
+ from [ len ] unless*
+ to [ 0 ] unless*
+ ] if
+ [ dup 0 < [ len + ] when 0 len clamp ] bi@
+ ! FIXME: make this work with steps
+ seq dup slice? [ collapse-slice ] when
+ step step-slice boa ;
+
+M: step-slice virtual-exemplar seq>> ; inline
+
+M: step-slice virtual@
+ [ step>> * ] [ from>> + ] [ seq>> ] tri ; inline