Money Distribution by Shares
MediumMath · Stripe
Split amount cents across accounts in proportion to their weights, so that every account gets a whole number of cents and the parts add up to exactly amount.
shares is a list of [account_id, weight] with unique account ids. Rows with weight <= 0 are ignored and do not appear in the output. Let W be the sum of the remaining weights.
- Each account first gets
floor(amount * weight / W)cents. - The cents left over (always fewer than the number of accounts) are handed out one each to the accounts with the largest fractional remainder, that is the largest value of
(amount * weight) mod W. - Ties in remainder go to the lexicographically smaller
account_id.
Return [account_id, cents] for every account with positive weight, sorted by account_id. If no account has positive weight, return [].
Example 1
- Input:
- amount = 1000, shares = [["acct_c", 3], ["acct_a", 1], ["acct_b", 3]]
- Output:
- [["acct_a", 143], ["acct_b", 429], ["acct_c", 428]]
- Explanation
- W = 7. acct_a is owed 1000 / 7 = 142.86 and acct_b and acct_c are owed 428.57 each, which floor to 142, 428 and 428 (sum 998), leaving 2 cents. The remainders
(1000 * w) mod 7are 6 for acct_a and 4 for both others, so acct_a gets one cent and the tie between acct_b and acct_c goes to acct_b.
Example 2
- Input:
- amount = 10, shares = [["z", 1], ["y", 1], ["x", 1]]
- Output:
- [["x", 4], ["y", 3], ["z", 3]]
- Explanation
- Each account is owed 3.33 cents and floors to 3, leaving 1 cent. All remainders are equal, so the smallest id
xtakes it.
Example 3
- Input:
- amount = 50, shares = [["fees", 0], ["ops", -4], ["main", 2]]
- Output:
- [["main", 50]]
- Explanation
- Only
mainhas a positive weight, so it receives everything and the other accounts are left out of the output.
Constraints
0 <= amount <= 10^90 <= shares.length <= 10^4-2^31 <= weight <= 2^31 - 1; account ids are unique