I feel like this should be simpler. I have N items. I want to distribute them as equally as possible to G people. If G divides N evenly, everyone gets N/G. The following tries to distribute the N=137 items to G=10 peoploe. I want some people to get 14 and some to get 13.
PROC IML;
N = 137;
G = 10;
/* split N items among G people? */
maxnum = ceil(N / G);
print maxnum;
items = j(G, 1);
do i = 1 to G;
if N >= maxnum then
items[i] = maxnum;
else
items[i] = maxnum - 1;
N = N - items[i];
end;
print items;
total = sum(items); /* did it work? */
print total N;
QUIT;
What am I doing wrong?
Close, but your logic is not quite right.
I wrote about this problem in the article, "Use the FLOOR-MOD trick to allocate items to groups."
If you use the function in that article, you get the right answer:
proc iml;
/* See
https://blogs.sas.com/content/iml/2019/04/08/floor-mod-trick-items-to-groups.html
B = total number of items or tasks (B >= 0, scalar)
k = total number of groups or workers (k > 0, scalar)
i = scalar or vector that specifies the group(s), max(i)<=k
Return the number of items to allocate to the i_th group */
start AssignItems(B, k, i);
n = floor(B / k) + (i <= mod(B, k)); /* the FLOOR-MOD trick */
return(n);
finish;
N = 137;
G = 10;
/* split N items among G people? */
idx = T(1:G);
items = AssignItems(N, G, idx);
print items;
total = sum(items); /* did it work? */
print total N;
By the way, notice that you do not need to loop over the number of groups. The FLOOR-MOD trick handles the assignment as a vector operation.
Close, but your logic is not quite right.
I wrote about this problem in the article, "Use the FLOOR-MOD trick to allocate items to groups."
If you use the function in that article, you get the right answer:
proc iml;
/* See
https://blogs.sas.com/content/iml/2019/04/08/floor-mod-trick-items-to-groups.html
B = total number of items or tasks (B >= 0, scalar)
k = total number of groups or workers (k > 0, scalar)
i = scalar or vector that specifies the group(s), max(i)<=k
Return the number of items to allocate to the i_th group */
start AssignItems(B, k, i);
n = floor(B / k) + (i <= mod(B, k)); /* the FLOOR-MOD trick */
return(n);
finish;
N = 137;
G = 10;
/* split N items among G people? */
idx = T(1:G);
items = AssignItems(N, G, idx);
print items;
total = sum(items); /* did it work? */
print total N;
By the way, notice that you do not need to loop over the number of groups. The FLOOR-MOD trick handles the assignment as a vector operation.
Very interesting. Thanks!
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.