Problem: We have x checkboxes and we want to check y of them evenly.
Example 1: select 50 checkboxes of 100 total.
[-]
[x]
[-]
[x]
...
Example 2: select 33 checkboxes of 100 total.
[-]
[-]
[x]
[-]
[-]
[x]
...
Example 3: select 66 checkboxes of 100 total:
[-]
[x]
[x]
[-]
[x]
[x]
...
But we're having trouble to come up with a formula to check them in code, especially once you go 11/111 or something similar. Anyone has an idea?
Here's a straightforward solution using integer arithmetic:
void check(char boxes[], int total_count, int check_count)
{
int i;
for (i = 0; i < total_count; i++)
boxes[i] = '-';
for (i = 0; i < check_count; i++)
boxes[i * total_count / check_count] = 'x';
}
total_count
is the total number of boxes, and check_count
is the number of boxes to check.
First, it sets every box to unchecked. Then, it checks check_count
boxes, scaling the counter to the number of boxes.
Caveat: this is left-biased rather than right-biased like in your examples. That is, it prints x--x--
rather than --x--x
. You can turn it around by replacing
boxes[i * total_count / check_count] = 'x';
with:
boxes[total_count - (i * total_count / check_count) - 1] = 'x';
Assuming 0 <= check_count <= total_count
, and that boxes
has space for at least total_count
items, we can prove that:
No check marks will overlap. i * total_count / check_count
increments by at least one on every iteration, because total_count >= check_count
.
This will not overflow the buffer. The subscript i * total_count / check_count
Will be >= 0
. i
, total_count
, and check_count
will all be >= 0
.
Will be < total_count
. When n > 0
and d > 0
:
(n * d - 1) / d < n
In other words, if we take n * d / d
, and nudge the numerator down, the quotient will go down, too.
Therefore, (check_count - 1) * total_count / check_count
will be less than total_count
, with the assumptions made above. A division by zero won't happen because if check_count
is 0, the loop in question will have zero iterations.