patterncMinor
Distribute an array of numbers equally
Viewed 0 times
arraydistributenumbersequally
Problem
The user will input two numbers, say 19 and 5. We need to equally divide 19 equally into 5 groups and output the start index and the end index of each group (using zero-based indexes). Example:
Grp 1: 0 1 2 3
Grp 2: 4 5 6 7
Grp 3: 8 9 10 11
Grp 4: 12 13 14 15
Grp 5: 16 17 18
The output should be
Grp 1: 0 3
Grp 2: 4 7
Grp 3: 8 11
Grp 4: 12 15
Grp 5: 16 18
I have written the program. But I feel it is not good. Can you please tell me if there is any other way.
Can anyone tell me how the solution could be optimized?
Grp 1: 0 1 2 3
Grp 2: 4 5 6 7
Grp 3: 8 9 10 11
Grp 4: 12 13 14 15
Grp 5: 16 17 18
The output should be
Grp 1: 0 3
Grp 2: 4 7
Grp 3: 8 11
Grp 4: 12 15
Grp 5: 16 18
I have written the program. But I feel it is not good. Can you please tell me if there is any other way.
#include
#define A 19
#define B 5
#define PER_ENTRY A/B
struct divide {
int start;
int end;
};
void calc_even(struct divide *div, int no)
{
int remain = A % B ;
int extra_add = 1;
if (no > remain) {
extra_add = 0;
}
static int priv_end = 0;
if (no == 1) {
div->start = 0;
div->end = (PER_ENTRY - 1) + extra_add ;
} else {
div->start = priv_end + 1;
if (no == B) {
div->end = A - 1;
} else {
div->end = div->start + (PER_ENTRY - 1) + extra_add ;
}
}
priv_end = div->end;
}
int main()
{
int i = 0;
struct divide num_diff[B];
for (i = 1 ; i <= B ; i++ ){
num_diff[i-1].start = 0;
num_diff[i-1].end = 0;
calc_even(&num_diff[i-1], i);
}
for (i = 1 ; i <= B ; i++ ) {
printf("Grp%d: %d %d \n", i, num_diff[i-1].start, num_diff[i-1].end);
}
}Can anyone tell me how the solution could be optimized?
Solution
There are a number of things that I see that may help you improve your program.
Avoid needless recalculation
There is a lot of calculation within the
Prefer
The use of
Think of the user
The program as currently coded needs to be recompiled if we want to try any other pair of numbers. It would be better to accept those parameters from the command line rather than making them fixed.
Use library functions
The program calculates both a quotient and remainder for a given pair of numbers. There is already a library function
Understand integer conversion rules
This code can be greatly simplified:
A boolean value, when converted to an
Use more descriptive names
The names you have chosen are generally not too bad, but
Reduce complex logic
The
Putting it all together
Applying all of these suggestions, an alternative might look like this:
Avoid needless recalculation
There is a lot of calculation within the
calc_even routine that doesn't need to be repeated for every step through the loop. Also, there are two separate loops in main -- one the calculates and stores the results and another that prints them. There is no reason that the results couldn't simply be generated and printed within a single loop. In addition to being more efficient in terms of computation, it would also use less memory since there would be no need to save the results. They can simply be calculated and discarded.Prefer
const to #defineThe use of
#define A 19 is better expressed as const int A = 19; because the latter has a defined type, while a #define does not enforce any notion of type.Think of the user
The program as currently coded needs to be recompiled if we want to try any other pair of numbers. It would be better to accept those parameters from the command line rather than making them fixed.
Use library functions
The program calculates both a quotient and remainder for a given pair of numbers. There is already a library function
div that does that in a single step.Understand integer conversion rules
This code can be greatly simplified:
int extra_add = 1;
if (no > remain) {
extra_add = 0;
}A boolean value, when converted to an
int in C is defined as 0 if it is false and 1 if it is true, so that bit of code can be expressed instead as:int extra_add = (no <= remain);Use more descriptive names
The names you have chosen are generally not too bad, but
A, B and no are not very good names. Reduce complex logic
The
calc_even calculations are entirely too complex for the requirements of the program. Think first about how you'd do this with pencil and paper. If we have 5 bins and 19 numbers, we divide to get a quotient (3) and remainder (4). So that means that all bins will have at least 3 numbers and 4 of the bins will have one extra.Putting it all together
Applying all of these suggestions, an alternative might look like this:
#include
#include
int main(int argc, char *argv[])
{
if (argc = 0");
return 1;
}
int bins = atoi(argv[2]);
if (bins = 0");
return 1;
}
div_t qr = div(number, bins);
int begin = 0;
for (int i=0; i < bins; ++i) {
int end = begin + qr.quot + (i < qr.rem);
printf("Grp %d: %d %d\n", i+1, begin, end-1);
begin = end;
}
}Code Snippets
int extra_add = 1;
if (no > remain) {
extra_add = 0;
}int extra_add = (no <= remain);#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc < 3) {
puts("Usage: divide number bins");
return 0;
}
int number = atoi(argv[1]);
if (number <= 0) {
puts("Error: number must be >= 0");
return 1;
}
int bins = atoi(argv[2]);
if (bins <= 0) {
puts("Error: bins must be >= 0");
return 1;
}
div_t qr = div(number, bins);
int begin = 0;
for (int i=0; i < bins; ++i) {
int end = begin + qr.quot + (i < qr.rem);
printf("Grp %d: %d %d\n", i+1, begin, end-1);
begin = end;
}
}Context
StackExchange Code Review Q#101006, answer score: 3
Revisions (0)
No revisions yet.