Considering the minimum common multiple of N and B: mcm, it is the worse case for the given N and B. (You will find no N+B where the optimal cut is worse than its MCM)
e.g. B=5, N=6 -> mcm = 30
The value of mcm can be factorized into prime numbers (factors). Each of the mcm little chunks could be grouped using those values and minimize the number of cuts.
Each factor can be used or not depending of your custom rules, in this case, allowing only chunks of equal size for all N persons.
Example of algorithm:
remainingB = B
foreach (f in factors)
while ( acceptChunkGrouping( f ) ) // yes, can be flattened easily.
distributeToEachPerson( f*B/mcm )
remainingB -= N * (f*B/mcm )
Following your example of B=5, N=6, mcm=30: factorization of 30 is:
(1), 2, 3, 5, 6:
- Chunks of 6*(1/6) -> rejected as there are no N x (1/6) chunks available.
- Chunks of 5*(1/6) -> rejected as there are no N x (5/6) chunks available.
- Chunks of 3*(1/6) -> Allowing N x (3/6) -> remaining 2 bars.
- Chunks of 2*(1/6) -> Allowing N x (2/6) -> remaining 0 bars.
- chunks of 1*(1/6) -> rejected as there are no N x (1/6) chunks available.
To force each person having chunks of the same size, the test could be:
var chunksPerBar = floor(1 / (factor*B/mcm))
if (chunksPerBar*remainingB >= N) then acceptTheFactor
An other example:
- B=26, N=4;
- mcm = 52;
- factors: 13, 2, (2), 1
- 13 is rejected.
- 2 is accepted, giving 6 full bars to each N persons.
- 1 is accepted, giving 0.5 bars to each N persons.
- Each person get 6 full bars + 1/2 bar.