{ "34_01_" } [ 2 0 3 "01_34_" [ exchange-subseq ] keep ] unit-test
{ "cdebaf" } [ 3 0 2 "abcdef" [ exchange-subseq ] keep ] unit-test
+
+{ { } } [ { } sequence-cartesian-product ] unit-test
+{ { } } [ { { } } sequence-cartesian-product ] unit-test
+{ { } } [ { { 1 2 } { } } sequence-cartesian-product ] unit-test
+{ { { 1 } { 2 } } } [ { { 1 2 } } sequence-cartesian-product ] unit-test
+
+{
+ {
+ { 1 3 5 6 { 9 } }
+ { 1 3 5 7 { 9 } }
+ { 1 4 5 6 { 9 } }
+ { 1 4 5 7 { 9 } }
+ { 2 3 5 6 { 9 } }
+ { 2 3 5 7 { 9 } }
+ { 2 4 5 6 { 9 } }
+ { 2 4 5 7 { 9 } }
+ }
+} [
+ { { 1 2 } { 3 4 } { 5 } { 6 7 } { { 9 } } } sequence-cartesian-product
+] unit-test
[ find drop ] keepd swap
[ cut ] [ f over like ] if* ; inline
+: ?cut ( seq n -- before after ) [ index-or-length head ] [ index-or-length tail ] 2bi ;
+
: nth* ( n seq -- elt )
[ length 1 - swap - ] [ nth ] bi ; inline
2dup _ exchange-unsafe
[ 1 - ] [ 1 + ] [ 1 + ] tri*
] [ pick 0 > ] swap while 3drop ;
+
+: sequence-cartesian-product ( seqs -- seqs' )
+ dup length 1 <= [
+ [ [ 1array ] map ] map concat
+ ] [
+ 2 cut [ first2 cartesian-product concat ] dip swap
+ [ [ suffix ] cartesian-map concat ] reduce
+ ] if ;