# How to represent a number as a list of sums? (Or How to stack up or fill given number into categories based on a given list?)

I have two set of lists:
first list (let us call it A) {121, 30, 70, 50} and
a second, list of list (call it B) {{90,10,30},{40,20,1},{10,70,20},{10,15,20}}
Following operations need to be performed to get the output list:

1. take the first element of list A and take first list of list B, in this case 121 and {90,10,30}

2. 121 can be divided or stacked (or filled) as 90+10+21=121 based on the list {90,10,30}, here full of 90 is used then full of 10 is used then only 21 of 30 is used. So the output for first value is {90,10,21} (Note: Elements are stacked from Left to right, ie., 10 starts filling only after 90 is fully filled and 30 starts filling only after 10 is fully filled)

• similarly for the second items 30 and {40,20,1} only 30 out of 40 is enough and then nothing of the others so, 0 of 20 and 0 of 1, so the output is {30,0,0} such that 30+0+0=30
• For the third items 70 and {10,70,20} full 10 out of 10 is used and then 60 of 70 and 0 of 20, so the output is {10,60,0} such that 10+60+0=70
• For the fourth items 50 and {10,15,20} full 10 out of 10 is used and then full 15 of 15 and full 20 of 20, so the output is {10,15,20} such that 10+15+20=45. NOTE: 45 is less than 50 but that is not a problem. The aim is to fully use the list to the maximum possible amounts from Left to Right and try to come close or satisfy the number.
3. Some Notes:
Numbers can be float. Integers are given here for only example and explanation purpose.
The size of the lists inside list B will all be the same, in this case 3 elements.
The size of the list A and corresponding B is much larger (around 8670 items) than shown in the example.
Summary:
Inputs: {121, 30, 70, 50} ; {{90,10,30},{40,20,1},{10,70,20},{10,15,20}}
Output: {{90,10,21},{30,0,0},{10,60,0},{10,15,20}}

Fun Fact: This logic is used in real life to dispatch power plants to supply electricity demand and it is called stack dispatch model. List A is the demand at a given hour, and list B are power plants available at that hour. Output is how much of each power plant is operated to satisfy the demand.

I am looking for a simple and efficient code for this operation. Any help is appreciated.

g = Differences @ Prepend @ Clip[Accumulate @ #2, {0, #}] &;


{{90, 10, 21}, {30, 0, 0}, {10, 60, 0}, {10, 15, 20}}


Here is a first attempt:

a = {121, 30, 70,
50};
b = {{90, 10, 30}, {40, 20, 1}, {10, 70, 20}, {10, 15, 20}}


Define function:

f[x_, y_] := Module[{w},
w = SplitBy[FoldList[Subtract, x, y], Sign][];
ArrayReshape[-Differences@Append[w, 0], 3, 0]
]


Apply to data:

MapThread[f, {a, b}]


yields:

{{90, 10, 21}, {30, 0, 0}, {10, 60, 0}, {10, 15, 20}}

Finally, got the chance to use FoldPairList :D - Even though the solution below is simpler, it's a little slower than @ubpdqn's answer:

Define the function

ClearAll[temp];

temp[n_, values_] := FoldPairList[{Min[##], #1 - Min[##]} &, n, values];


Apply to data

MapThread[temp, {a, b}]

(* Out: {{90, 10, 21}, {30, 0, 0}, {10, 60, 0}, {10, 15, 20}} *)

a = {121, 30, 70, 50};
b = {{90, 10, 30}, {40, 20, 1}, {10, 70, 20}, {10, 15, 20}};

accumulateWhile[{a_Integer, b_List}] :=
Differences@FoldList[If[#1 + #2 <= a, #1 + #2, a] &, 0, b]

accumulateWhile /@ Transpose[{a, b}]


{{90, 10, 21}, {30, 0, 0}, {10, 60, 0}, {10, 15, 20}}

 a = {121, 30, 70, 50};
b = {{90, 10, 30}, {40, 20, 1}, {10, 70, 20}, {10, 15, 20}};
Transpose@Ramp[# - Ramp[Accumulate@# - Threaded@a]] &@Transpose@b

{{90, 10, 21}, {30, 0, 0}, {10, 60, 0}, {10, 15, 20}}

n = 10^6;
a = RandomReal[{1, 100}, n];
b = RandomReal[{100, 200}, {n, 3}];

f = Transpose@Ramp[#2 - Ramp[Accumulate@#2 - Threaded@#1]] &;
g = Differences@Prepend@Clip[Accumulate@#2, {0, #}] &;

r1 = MapThread[g]@{a, b}; // RepeatedTiming
r2 = f[a, Transpose@b]; // RepeatedTiming
r1 == r2

{2.84142, Null}
{0.047036, Null}
True