Как получить равное количество элементов после деления диапазона, оставляя остаток
Различные подходы.
Ключевой вопрос заключается в том, включены ли 0
и 10
в целочисленный диапазон: это [0... 10]
или [0... 10)
или ...? Обратите внимание на ]
или )
? Предположим, что конечные точки списков включены, а [0... 10]
- это 11 различных целочисленных значений.
Примечание. Существуют такие крайности, как 11 чисел, разделенных на 12 групп.
Ниже представлен поддиапазон из первой 1/n
части диапазона, затем 1/(n-1)
части оставшегося диапазона и т. Д.
void range(int n, int inclusive_min, int inclusive_max) {
printf("Range [%d %d] / %d\n", inclusive_min, inclusive_max, n);
for(int i = n; i > 0 && inclusive_min <= inclusive_max; i--) {
int range = 1 + inclusive_max - inclusive_min;
int sub_range = range/i;
if (sub_range == 0) sub_range = 1;
printf("Sub range [%d %d]\n", inclusive_min, inclusive_min + sub_range - 1);
inclusive_min += sub_range;
}
}
int main(void) {
range(3, 0, 10);
range(2, 0, 10);
range(5, 0, 10);
range(3, 0, 1);
return 0;
}
выход
Range [0 10] / 3
Sub range [0 2]
Sub range [3 6]
Sub range [7 10]
Range [0 10] / 2
Sub range [0 4]
Sub range [5 10]
Range [0 10] / 5
Sub range [0 1]
Sub range [2 3]
Sub range [4 5]
Sub range [6 7]
Sub range [8 10]
Range [0 1] / 3
Sub range [0 0]
Sub range [1 1]
Более элегантное решение, похожее на Алгоритм линии Брезенхема
void range(int n, int inclusive_min, int inclusive_max) {
printf("Range [%d %d] / %d\n", inclusive_min, inclusive_max, n);
int range = 1 + inclusive_max - inclusive_min;
int sub_range = range / n;
int sub_range_res = range % n;
int p = 0;
for (int i = 0; i < n; i++) {
int next = inclusive_min + sub_range;
p += sub_range_res;
if (2 * p >= n) { // like p >= n/2 without integer truncation.
p -= n;
next++;
}
if (next > inclusive_min) {
printf("Sub range %d:[%d %d]\n", i, inclusive_min, next - 1);
}
inclusive_min = next;
}
}
выход
Range [0 10] / 3
Sub range 0:[0 3]
Sub range 1:[4 6]
Sub range 2:[7 10]
Range [0 10] / 2
Sub range 0:[0 5]
Sub range 1:[6 10]
Range [0 10] / 5
Sub range 0:[0 1]
Sub range 1:[2 3]
Sub range 2:[4 6]
Sub range 3:[7 8]
Sub range 4:[9 10]
Range [0 1] / 3
Sub range 0:[0 0]
Sub range 2:[1 1]