Assigning Numbers to Groups – Problem #2: Distribute 1 Per Group or Even/Odd

The other day I was trying to assign a container of, let’s say, numbers distributed across 20 groups, to a container with a smaller size that can only hold up to 6 groups. The bigger group has values from 0 to 19. It also means that group 0 will always have zero number value, 1 will be 1 and so on.

This finite range of values comes in randomly.

Take note that the producer of these values will most likely have distributed the numbers as evenly into evens and odds. That means if there were 99 values distributed across 20 groups, there should be 5 zeroes, 5 ones and so on, and the last group will have 4 nineteens (did I get that right? 🤔). Okay, but you get the picture. right?

The objective was to reassign the values of the larger set to the smaller one as evenly as possible. Picture it this way, it may look something like this in the end:

[0] = {*, *, *, *}

[1] = {*, *, *, *}

[2] = {*, *, *}

[3] = {*, *, *}

[4] = {*, *, *}

[5] = {*, *, *}

Let us have for example the following values below. Consider each element in the Integer array as belonging to a group of the same number as the value.

Integer[] groups = new Integer[]{8, 1, 2, 12, 3 ,19 ,7 ,6 , 4, 10, 9, 13, 11, 5, 14, 15, 18, 17, 16, 0}

Solution 1 – Distribute into one per group

This is pretty much self explanatory. We’re just re-assigning to the next group that comes in the order from lowest to highest. We reset the counter to zero once it reaches the target value.

/* --- Java code --- */

1        int ctr = 0;
2        int target = 6;
3        int assignment = 0;
4
5        for (Integer i : groups) {
6            assignment = ctr;
7            ctr++;
8            if (ctr >= target) ctr = 0;
9            log.info("RESULT >> Assignment for element {} is now: {}", i, assignment);
10       }
RESULT >> Assignment for element 8 is now: 0
RESULT >> Assignment for element 1 is now: 1
RESULT >> Assignment for element 2 is now: 2
RESULT >> Assignment for element 12 is now: 3
RESULT >> Assignment for element 3 is now: 4
RESULT >> Assignment for element 19 is now: 5
RESULT >> Assignment for element 7 is now: 0
RESULT >> Assignment for element 6 is now: 1
RESULT >> Assignment for element 4 is now: 2
RESULT >> Assignment for element 10 is now: 3
RESULT >> Assignment for element 9 is now: 4
RESULT >> Assignment for element 13 is now: 5
RESULT >> Assignment for element 11 is now: 0
RESULT >> Assignment for element 5 is now: 1
RESULT >> Assignment for element 14 is now: 2
RESULT >> Assignment for element 15 is now: 3
RESULT >> Assignment for element 18 is now: 4
RESULT >> Assignment for element 17 is now: 5
RESULT >> Assignment for element 16 is now: 0
RESULT >> Assignment for element 0 is now: 1

Solution 2 – Even and odd assignments

Here we are determining if the value that came in is even or odd. Once evaluated, we assign that value to the 1st even group, then increment the group by 2. The same goes for odd values.

/* --- Java code --- */

1        int evenCtr = 0;
2        int oddCtr = 1;
3        int target = 6;
4        int assignment = 0;
5
6        for (Integer i : groups) {
7            if (i % 2 == 0) {
8                assignment = evenCtr;
9                evenCtr += 2;
10               if (evenCtr >= target) evenCtr = 0;
11           } else if (i % 2 == 1) {
12               assignment = oddCtr;
13               oddCtr += 2;
14               if (oddCtr >= target) oddCtr = 1;
15           }
16           log.info("RESULT >> Assignment for element {} is now: {}", i, assignment);
17       }
RESULT >> Assignment for element 8 is now: 0
RESULT >> Assignment for element 1 is now: 1
RESULT >> Assignment for element 2 is now: 2
RESULT >> Assignment for element 12 is now: 4
RESULT >> Assignment for element 3 is now: 3
RESULT >> Assignment for element 19 is now: 5
RESULT >> Assignment for element 7 is now: 1
RESULT >> Assignment for element 6 is now: 0
RESULT >> Assignment for element 4 is now: 2
RESULT >> Assignment for element 10 is now: 4
RESULT >> Assignment for element 9 is now: 3
RESULT >> Assignment for element 13 is now: 5
RESULT >> Assignment for element 11 is now: 1
RESULT >> Assignment for element 5 is now: 3
RESULT >> Assignment for element 14 is now: 0
RESULT >> Assignment for element 15 is now: 5
RESULT >> Assignment for element 18 is now: 2
RESULT >> Assignment for element 17 is now: 1
RESULT >> Assignment for element 16 is now: 4
RESULT >> Assignment for element 0 is now: 0

Notice I’ve mixed Integer class and primitive int in the examples above. Well, that’s all fine for illustration purposes here. In practice, I’ve always made it of the same type as much as possible.

I have not tried the code above for negative numbers. Given that the problem will always be positive integers, I didn’t bother to check. That might not be always the case, the producer might bug out and provide a negative number. In that case changing == 1 to != 0 should do the trick.

In reality, I stopped short of coming up with other solutions (Any input is welcome though). Later on I discovered that the target system allows for null values for a group. That is if you assign as null, it will take care of distributing the groupings in a round-robin fashion. So rather than putting in extra lines of code and having to test it (Yes, lesser JUnit tests 🤣), I opted for letting the target system handle the outcome of the groupings.

Similar Posts: