Как равномерно разделить элементы на группы в заданных пропорциях?
Имеется массив/перечислимый объект некоторых элементов. Есть три группы, на которые нужно разделить этот массив элементов в заданных пропорциях А, B, C (A+B+C=1). То есть если всего элементов N, то в первой группе окажется N*A элементов, во второй N*B элементов, в третьей - N*С. Причем элементы попали в эти группы наиболее равномерным (насколько это возможно) образом, то есть вероятности попадания элемента в любую из групп одинаковы.
Необходимо написать алгоритм этого разделения. Желательно на Java.
Условное дано:
double A; //доля первой группы
double B; //доля второй группы
double C; //доля третьей группы
int[] items; // элементы
В своих изысканиях я придумал следующий алгоритм. По заданной доле и количеству элементов вычисляется, сколько элементов будет в группе. По этому количеству определяется шаг, с которым будет проходиться список элементов. Алгоритм с конца проходит список извлекая из него элементы через указанный шаг, и складывая его в накапливаемую группу. Функция возвращает выделенную группу и применяется к оставшимся элементам уже с другим значением доли.
private static List<Integer> take(List<Integer> items, int count) {
double step = (double) items.size() / count;
int size = items.size();
List<Integer> res = new LinkedList<>();
for (int i = 0; i < count; i++) {
int index = (int) Math.round(size - 1 - i * step);
Integer item = items.remove(index);
res.add(0, item);
}
return res;
}
Алгоритм в целом работает, но качество его равномерности математически оценить сложно. Визуально получается так:
- Для пяти элементов
A = 55,00% B = 35,00% C = 10,00%
0 1 2 3 4
C A A B A
---------------
A A A
B
C
- Для десяти элементов
A = 55,00% B = 35,00% C = 10,00%
0 1 2 3 4 5 6 7 8 9
B A A C A B A A B A
------------------------------
A A A A A A
B B B
C
- Для десяти элементов
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
B A C A A B A B A B A B A C A A B A B A
------------------------------------------------------------
A A A A A A A A A A A
B B B B B B B
C C
Прошу сообщество попытаться оценить качество такого решения и предложить варианты улучшения или альтернативы. Возможно, такая задача уже решена математиками или некоторыми программистами.