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!
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.