BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
WeiChen
Obsidian | Level 7

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?

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

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.

View solution in original post

2 REPLIES 2
Rick_SAS
SAS Super FREQ

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.

WeiChen
Obsidian | Level 7

Very interesting. Thanks!

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 2 replies
  • 943 views
  • 4 likes
  • 2 in conversation