Two simple vector partition rules

We have a vector of zeros and other numbers, f.e:

vector = {0, 0, 0, 9, 0, 2, 0, 5, 0, 4, 0, 5, 6, 2, 0};


The two rules:

Partition the vector in such a way that (1) at most two zeros are in one bin and (2) no bin should contain more than five elements.

The correct result for the above vector would be:

{{0, 0}, {0, 9, 0}, {2, 0, 5, 0}, {4, 0, 5, 6, 2}, {0}}

Doesn't sound too difficult, but I was only able to find a procedural solution:

Baskets[dt_] :=
Module[{rl = {}, sl = {}, n = 1, le = Length[dt]},
While[n < le,
While[Length[sl] < 5 && Count[sl, 0] < 2 && n <= le,
AppendTo[sl, dt[[n++]]]];
AppendTo[rl, sl];
sl = {}];
If[Length @ Flatten[rl] < le, AppendTo[rl, {dt[[-1]]}]];
rl]



{{0, 0}, {0}}

Baskets[{0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0}]


{{0, 0}, {1, 0, 0}, {1, 0, 1, 0}, {0, 0}, {0}}

What would a functional solution look like?

• Would this not be a correct solution: {{0, 0}, {0, 9, 0, 2}, {0, 5, 0, 4}, {0, 5, 6, 2, 0}}? This related post can solve such tasks.
– Syed
Aug 10, 2023 at 14:21
• Almost - if the last bin would be {0, 5, 6 , 2, 0}. I think it is easier to run from left to right and stop when one of the two rules is fulfilled, in this case, when a 2nd zero is found.
– eldo
Aug 10, 2023 at 14:22
• My bad, I corrected this after deleting the previous comment, you are right. I am using cSplit3[vector, Length[#] <= 5 && Count[#, 0] <= 2 &]
– Syed
Aug 10, 2023 at 14:24

ClearAll[f]
f[val_, maxcount_, binlength_] := Module[{$$s = 0,$$l = 0},
Split[#,
Or[($$s += Boole[# == val]) < maxcount && ++$$l < binlength,
$$s = 0;$$l = 0] &]] &

f[0, 2, 5] @ vector

{{0, 0}, {0, 9, 0}, {2, 0, 5, 0}, {4, 0, 5, 6, 2}, {0}}


Here's one way

SequenceCases[vector, _?(Count[#, 0] <= 2 && Length[#] <= 5 &)]

• Thank you, this really motivates me to learn more about the Sequence-functions (I only recently upgraded)
– eldo
Aug 10, 2023 at 16:24