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!

SAS Innovate 2025: Register Now

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!

Multiple Linear Regression in SAS

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.

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