Randomizing Workplace Meetups
Many companies are experimenting with randomly assigning employees into small groups for virtual coffee breaks or video hangouts. The goal is to recreate the chance encounters that naturally happen around shared spaces. If you're implementing this yourself, the underlying programming problem is straightforward: divide n people into groups of at least size g, while minimizing the size difference between groups. For example, 15 employees split into groups of at least four becomes 5, 5, 5; with 16 you get 4, 4, 4, 4; with 17 you get 4, 4, 4, 5.
A straightforward Python implementation might start by creating n//g groups of size g and then distributing the remainder across those groups.
groups = [g] * (n//g)
for e in range(0, n % g):
groups[e % len(groups)] += 1
Here, the first line creates n//g groups of size g (using integer division). The for loop handles the leftover elements. For instance, with g == 4 and n == 17, you start with four groups of four and add one element to a group, yielding [5, 4, 4, 4].
The expression e % len(groups) matters when the number of leftovers exceeds the number of groups. If g == 4 and n == 11, you have [4, 4] with three elements to distribute across just two groups, so the modulo wraps around.
This works, but it feels like there should be a cleaner formula. A more naive approach helps visualize the distribution process.
groups = [0] * (n//g)
for i in range(n):
groups[i % len(groups)] += 1
While this implementation loops n times, it clarifies the mechanics. With g == 4 and n == 17, each element is assigned to a group sequentially, filling up the list like this:

The result is [5, 4, 4, 4]. Observing this, you can calculate the increment count for each group position without iterating. The number of times groups[i] gets incremented equals how many full passes the naive loop makes over that position.
That insight leads to a formula that builds the entire list in one pass.
groups = [1+max(0,n-(i+1))//(n//g) for i in range(n//g)]
In this version, n//g tells you the number of groups, and each entry is calculated as 1 + max(0, n-(i+1))//(n//g). The logic breaks down as follows:
- The
1accounts for the first element assigned to each group position. max(0, n-(i+1))counts the elements remaining after placing that initial1in each group up to positioni. Dividing byn//ggives the number of additional full passes those leftovers contribute to positioni.
To see this in action, consider computing groups[0] with n == 17 and g == 4. You place 1 in that position, leaving 16 elements. Sharing the remainder across four groups means four full passes, so you add 16/4 = 4 elements, making groups[0] equal to 5. For groups[1], you place 1, leaving 15 elements; integer division gives 15/4 = 3, so that group ends up with 4.
This one-liner is concise and efficient, but it's worth noting that the simpler looping solutions are perfectly readable. The formula trades explicit steps for compactness, and for many developers the clarity of the naive version may be a better maintenance trade-off.
4 [4]
5 [5]
6 [6]
7 [7]
8 [4, 4]
9 [5, 4]
10 [5, 5]
11 [6, 5]
12 [4, 4, 4]
13 [5, 4, 4]
14 [5, 5, 4]
15 [5, 5, 5]
16 [4, 4, 4, 4]
17 [5, 4, 4, 4]


