While trying to craft up a mergesort in C as an exercise, I am encountering a weird issue where the output of the algorithm changes with the presence of a printf. Let me elaborate it further. I have a "MergeSort.h" file in which I have my mergesort algorithm as follows:
#ifndef _MSORT_H_
#define _MSORT_H_
void merge(int a[],int lo,int mi,int hi){
int n1 = (mi - lo) +1;
int n2 = hi - mi;
int left[n1];
int right[n2];
int i;
int j;
int k;
for(i = 0;i < n1;i++){
left[i] = a[lo+i];
}
for(j = 0;j < n2;j++){
right[j] = a[mi+j+1];
}
i = 0;
j = 0;
for(k = lo;k <= hi;k++){
if(left[i] < right[j]){
a[k] = left[i];
i = i + 1;
}else{
a[k] = right[j];
j = j+1;
}
}
}
void msorthelper(int a[],int p,int r){
if(p < r){
int mid = (p + r)/2;
msorthelper(a,0,mid);
msorthelper(a,mid+1,r);
merge(a,p,mid,r);
}
}
void msortex(int a[],int size){
msorthelper(a,0,size-1);
int counter;
for(counter = 0;counter < size;counter++){
printf(" %d ",a[counter]);
}
}
#endif
I have my corresponding sort tester in sorttester.c:
#include <stdio.h>
#include "mergesort.h"
int main(){
int out[] = {8,1,6};
msortex(out,3);
}
The output from running the sorttester is as follows:
1 0 0
Now here's the interesting part, when I put any printf statement to the beginning of the merge, the correct output is generated. Here's an example:
#ifndef _MSORT_H_
#define _MSORT_H_
void merge(int a[],int lo,int mi,int hi){
printf("Hello\n");
int n1 = (mi - lo) +1;
int n2 = hi - mi;
int left[n1];
int right[n2];
.................Rest of the code.....
The output now is:
HelloHello 1 6 8
This is the correct sorted order for the array 8 6 1.
Can somebody tell me what I might be doing wrong here that is causing the output to be drastically by the presence of a printf?
Thanks
Have a look at your merging part of code:
for(k = lo;k <= hi;k++){
if(left[i] < right[j]){
a[k] = left[i];
i = i + 1;
}else{
a[k] = right[j];
j = j+1;
}
}
Lets assume that
left[] = {1, 2}
right[] = {3, 4, 5}
After 2 iterations of your merging loop (k) the value of "i" will be 2. From now on, you will try to compare
left[2] < right[j]
Which is invalid, as left[2] will refer to some random memory (left array size is only 2, so element of index 2 doesnt exist, only 0 and 1)
So, if you add guards for the i and j values, for example by changing first if condition to:
if(i != n1 && (j == n2 || left[i] < right[j])){
You should be fine.
Anyway, I should also tell you that you shouldnt declare array sizes with values that are not const, like:
int left[n1];
int right[n2];
Its actually forbidden by standard. You should either allocate it dynamically, use vectors(if c++) or jus declare them global with large enough size (maximum n value)
Related
I hope i made my self clear enough in the title but if not i am here to explain my self
i got an array from an input ( like Arr = {, ).
we can use only 1 additional array (1 original 1 additional)
this is what i made so far :
I made a new array named newArr and assigned it all the values Arr contains.
i sorted it (because its requires time complexity of nlogn)
and then moved duplicates to the end.
now what i can't figure out :
now i need to move the original digits to their place according to the main
(all the values in the arrays are positive and they can be bigger then
n-which is the size of the array and ofc they can be also smaller then n)
i also need to return the number of original digits in the array
the original number should stay in the same position and the duplicates in the end of the array their order doesn't matter.
from here we can't use another additional array only the current arrays that we have ( which are 2)
i have been thinking about doing some kind of binary search but all of them went wrong.(like bin_search_first) and original binary and still couldn't manage it.
can some one give me an hint?
here is the code at where i am
#define _CRT_SECURE_NO_WARNINGS
/*Libraries*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int* input_array(int);
int moveDuplicatesV2(int*, int);
void merge(int* a, int p, int q, int r);
void merge_sort(int* a, int first, int last);
void swap(int* v, int* u);
int bin_search_first(int , int* , int );
int main()
{
int arr[10] = { };
int n = 12;
int k = 0;
int first = 0;
int last = n - 1;
int mid = (first + last) / 2;
int l = n - 1;
int* D = arr + 1;
int j = 0;
size_t dupes_found = 0;
int* newArr = (int*)malloc(12 * sizeof(int));
assert(newArr);
for (int i = 0; i < n; i++)
{
newArr[i] = arr[i];
}
merge_sort(newArr, first, last);
for (size_t i = 0; i < n - 1 - dupes_found;)
{
if (newArr[i] == newArr[i + 1])
{
dupes_found++;
int temp = newArr[i];
memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
newArr[n - 1] = temp;
}
else {
i++;
}
}
j = 0;
int key = 0;
first = 0;
for (int i = 0; i < n - dupes_found; i++)
{
key = newArr[i];
first = bin_search_first(key, arr,n);
swap(&newArr[i], &newArr[first]);
newArr[first] = newArr[i];
}
for (int i = 0; i < n; i++)
{
arr[i] = newArr[i];
}
for (int i = 0; i < n; i++)
{
printf("%d", arr[i]);
}
return n - dupes_found;
}
void merge(int* a, int p, int q, int r)
{
int i = p, j = q + 1, k = 0;
int* temp = (int*)malloc((r - p + 1) * sizeof(int));
assert(temp);
while ((i <= q) && (j <= r))
if (a[i] < a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
while (j <= r)
temp[k++] = a[j++];
while (i <= q)
temp[k++] = a[i++];
/* copy temp[] to a[] */
for (i = p, k = 0; i <= r; i++, k++)
a[i] = temp[k];
free(temp);
}
void merge_sort(int* a, int first, int last)
{
int middle;
if (first < last) {
middle = (first + last) / 2;
merge_sort(a, first, middle);
merge_sort(a, middle + 1, last);
merge(a, first, middle, last);
}
}
void swap(int* v, int* u)
{
int temp;
temp = *v;
*v = *u;
*u = temp;
}
int bin_search_first(int key, int* a, int n)
{
int low, high, mid;
low = 0;
high = n - 1;
while (low <= high)
{
mid = (low + high) / 2; // low + (high - low) / 2
if (key > a[mid])
low = mid + 1;
else
if (key < a[mid])
high = mid - 1;
else //key==a[mid]
if ((low == high) || (a[mid - 1] < key))
return mid;
else
high = mid - 1;
}
return -1;
}
Here is my idea:
Sort the array (nlogn)
Loop over the array and for each value, save a pointer to its first occurence (n)
Loop over the original array and insert the value into a result array if it is the values first occurrence. Whether or not it is the first occurrence can be checked using the sorted array: each element in this array has an additional flag that will be set if the value has already been seen. So, search for the element using bsearch, if seen append to back of result array (order does not matter), if not seen append to beginning of array and set seen value. (nlogn, since bsearch doesn't need to seek the first element because it was precomputed thus logn, over the array n)
Here is an example code (you can replace the qsort by mergesort to make the algorithm actually nlogn, I just used qsort because it is given):
#include <stdio.h>
#include <stdlib.h>
struct arr_value {
int value;
int seen;
struct arr_value *first;
};
int compar(const void *p1,const void *p2) {
struct arr_value *v1 = (struct arr_value *)p1;
struct arr_value *v2 = (struct arr_value *)p2;
if(v1->value < v2->value) {
return -1;
} else if(v1->value == v2->value) {
return 0;
}
return 1;
}
int main()
{
#define NumCount (12)
int arr[NumCount] = { 7, 3, 1, 2, 7, 9, 3, 2, 5, 9, 6, 2 };
int arrResult[NumCount];
int resultCount = 0;
int resultCountBack = 0;
struct arr_value arrseen[NumCount];
for(int i = 0; i < NumCount; ++i) {
arrseen[i].value = arr[i];
arrseen[i].seen = 0;
}
qsort(arrseen, NumCount, sizeof(struct arr_value), compar);
struct arr_value *firstSame = arrseen;
firstSame->first = firstSame;
for(int i = 1; i < NumCount; ++i) {
if(arrseen[i].value != firstSame->value) {
firstSame = arrseen + i;
}
arrseen[i].first = firstSame;
}
struct arr_value key;
for(int i = 0; i < NumCount; ++i) {
key.value = arr[i];
struct arr_value *found = (struct arr_value *)bsearch(&key, arrseen, NumCount, sizeof(struct arr_value), compar);
struct arr_value *first = found->first;
if(first->seen) {
// value already seen, append to back
arrResult[NumCount - 1 - resultCountBack] = first->value;
++resultCountBack;
} else {
// value is new, append
arrResult[resultCount++] = first->value;
first->seen = 1;
}
}
for(int i = 0; i < NumCount; ++i) {
printf("%d ", arrResult[i]);
}
return 0;
}
Output:
7 3 1 2 9 5 6 2 9 2 3 7
To begin with, memmove doesn't run in a constant time, so the loop
for (size_t i = 0; i < n - 1 - dupes_found;)
{
if (newArr[i] == newArr[i + 1])
{
dupes_found++;
int temp = newArr[i];
memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
newArr[n - 1] = temp;
}
else {
i++;
}
}
drives the time complexity quadratic. You have to rethink the approach.
It seems that you are not using a crucial point:
all the values in the arrays are positive
It seriously hints that changing values to their negatives is a way to go.
Specifically, as you iterate over the initial array, and bin-search its elements in temp, comparing the _ absolute values_. When an element is found in temp, and it is still positive there, flip all its dupes in temp to negative. Otherwise flip it in initial.
So far, it is O(n log n).
Then perform an algorithm known as stable_partition: all positives are moved in front of negatives, retaining the order. I must not spell it here - I don't want to deprive you of a joy figuring it out yourself (still O(n log n)
And finally flip all negatives back to positives.
How do I make my code more efficient (in time) pertaining to a competitive coding question (source: codechef starters 73 div 4):
(Problem) Chef has an array A of length N. Chef wants to append a non-negative integer X to the array A such that the bitwise OR of the entire array becomes = Y .
Determine the minimum possible value of X. If no possible value of X exists, output -1.
Input Format
The first line contains a single integer T — the number of test cases. Then the test cases follow.
The first line of each test case contains two integers N and Y — the size of the array A and final bitwise OR of the array A.
The second line of each test case contains N space-separated integers A_1, A_2, ..., A_N denoting the array A.
Please don't judge me for my choice of language .
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int* binary_number(int n) // returns pointer to a array of length 20(based on given constrains) representing binary
{
int* ptc;
ptc = (int*) malloc(20*sizeof(int));
for(int i = 0; i < 20; i++)
{
if((n / (int) pow(2,19-i)) > 0){*(ptc + i) = 1;}
else {*(ptc + i) = 0;}
n = n % (int) pow(2,19-i) ;
}
return ptc;
}
int or_value(int* ptc, int n) // Takes in pointers containing 1 or zero and gives the logical OR
{
for(int k = 0; k < n; n++)
{
if(*ptc == *(ptc + 20*k)){continue;} // pointers are 20 units apart
else{return 1;break;}
}
return *ptc;
}
int main(void) {
int t; scanf("%d", &t);
for (int i = 0; i < t; i++)
{
int n, y;
scanf("%d %d", &n, &y);
int a[n];
for(int j = 0; j < n ; j++)
{
scanf("%d", &a[j]);
}
int b[20*n];
for (int j = 0; j < n; j++)
{
for (int k = 0; k < 20; k++)
{
b[20*j + k] = *(binary_number(a[n])+k);
}
}
int c = 0;
int p = 0;
for (int j = 0; j < 20; j++)
{
if ((*(binary_number(y) + j) == 1) && (or_value((&b[0] + j),n) == 0)){c = c + pow(2,19 - j);}
else if ((*(binary_number(y) + j) == 0) && (or_value((&b[0] + j),n) == 1)){p = 1; break;}
}
if (p==1){printf("-1");}
else {printf("%d\n", c);}
}
return 0;
}
I wanted to try and do a C implementation but the results were strange because, when it came to the mergesort algorithm, given the length of the array (even if the its elements where pseudo-random thanks to rand()). Every time it finished running the complexity was actually the same. I know, trying to understand the "problem" this way is not easy so this is the code that I've been written/copied from the internet:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DIM 1000000
void merge(int*, int, int, int);
void mergesort(int*, int, int);
int complexity=0; //Complexity is the variable that counts how many times the program goes through the relevant cycles
int main(int argc, char *argv[]){
int v[DIM], i;
time_t t;
srand((unsigned)time(&t));
for(i=0; i<DIM; i++){
v[i]=rand()%100;
printf("%d\n", v[i]);
}
mergesort(v, 0, DIM-1);
for(i=0; i<DIM; i++)
printf("%d\t", v[i]);
printf("\n");
printf("iterations: %d\n", complexity);
return 0;
}
void mergesort(int v[], int lo, int hi){
int mid;
if(lo<hi){
mid=(lo+hi)/2;
mergesort(v, lo, mid);
mergesort(v, mid+1, hi);
merge(v, lo, mid, hi);
}
return;
}
//This implementation is not actually mine, I got it from a site because I couldn't figure out why mine wouldn't run and order the input
void merge(int v[], int p, int q, int r) {
int n1, n2, i, j, k, *L, *M;
n1 = q - p + 1;
n2 = r - q;
//creation and initialization of the left and right vectors
L=(int*)malloc(n1*sizeof(int));
M=(int*)malloc(n2*sizeof(int));
for (i = 0; i < n1; i++){
L[i] = v[p + i];
complexity++;
}
for (j = 0; j < n2; j++){
M[j] = v[q + 1 + j];
complexity++;
}
//merging section
i = 0;
j = 0;
k = p;
while (i < n1 && j < n2) {
if (L[i] <= M[j]) {
v[k] = L[i];
i++;
complexity++;
} else {
v[k] = M[j];
j++;
complexity++;
}
k++;
}
//from what I understood this should be the section where what is left out gets copied inside the remaining spots
while (i < n1) {
v[k] = L[i];
i++;
k++;
complexity++;
}
while (j < n2) {
v[k] = M[j];
j++;
k++;
complexity++;
}
return;
}
I'll leave an image to a few trials I did with various sorting algorithms down here as well
Here is the question: is it normal to have the variable that counts temporal complexity constant? My initial thoughts were that it was due to bad implementation of the counter, I have no idea of how to prove it though simply because my knowledge of the algorithm is not that strong.
If that ends up being the correct answer can you direct me towards an implementation (not too complicated but still functional) of the counter to evaluate temporal complexity more precisely?
Edit: The columns A to I of the excel screenshot that I uploaded correspond to the length of the randomly generated array the values are: 100, 500, 1000, 5000, 10000, 50000, 1000000.
No matter the contents of the arrays, the merge function increments complexity by 2(r-p+1). Since the merge function is the only part of the code that depends on the contents of the array, this shows that the complexity variable is incremented a fixed number of times overall.
Here's a sketch of why the merge function increments complexity by 2(r-p+1):
This block increments it by n1:
for (i = 0; i < n1; i++){
L[i] = v[p + i];
complexity++;
}
This block by n2:
for (j = 0; j < n2; j++){
M[j] = v[q + 1 + j];
complexity++;
}
In the remaining code, i and j start at 0, and at each step either i or j is incremented by 1 and complexity increased. When the function returns, i is n1 and j is n2, so this adds another n1+n2 to complexity.
Since n1 = q-p+1 and n2 = r-q, overall the merge function increments complexity by 2*n1 + 2*n2 = 2(q-p+1+r-q) = 2(r-p+1).
I want to sort the int type list. but when parameter in merge function is double list, it works! but not when it is int list...
Here is sorting function. parameter is int pointer.
if Changing an int list to a double list works fine.
ex) int *a -> double *a
ex) int *l, *r1 -> double *l, *r1
ex) l = (int *)calloc(n1+1,sizeof(int)), r1 = (int *)calloc(n2+1,sizeof(int))
-> l = (double *)calloc(n1+1,sizeof(double)) r1 = (double *)calloc(n2+1,sizeof(double))
void merge(int *a, int p, int q, int r) {
int n1 = q - p + 1;
int n2 = r - q;
int *l, *r1;
int i, j, k;
l = (int *)calloc(n1 + 1, sizeof(int));
r1 = (int *)calloc(n2 + 1, sizeof(int));
for (i = 0; i < n1;i++)
l[i] = a[p + i];
for (j = 0; j < n2; j++)
r1[j] = a[q + 1 + j];
l[n1] = 10000;
r1[n2] = 10000;
i = 0;
j = 0;
for (k = p; k <= r; k++) {
if (l[i] <= r1[j]) {
a[k] = l[i];
++i;
} else {
a[k] = r1[j];
++j;
}
}
return;
}
here is recursive function. Until the length of the list is 1
ex) int *a -> double *a
void merge_sort(int *a, int p, int r) {
if (p < r) {
int q = (p + r) / 2;
merge_sort(a, p, q);
merge_sort(a, q + 1, r);
merge(a, p, q, r);
}
}
Create a list of length 10 and put it in the mergesort function. Then print the list.
int main(int argc, char *argv[]) {
int i, *a[10];
for (i = 0; i < 10; i++) {
a[i] = rand() % 10 + 1;
}
merge_sort(a, 0, 10);
for (i = 0; i < 10; i++) {
printf("%d ", a[i]);
}
return 0;
}
result is
0 0 0 2 5 10 9 9 3 5
There are multiple problems in your code:
if you wish to change the type of the array element, you must change it everywhere, including in the main function and you must also change the printf format. Increasing the warning level (gcc -Wall -Wextra -Werror) would prevent silly mistakes.
the definition of a in main is incorrect, it should be int a[10];, not an array of pointers to int.
you pass the total number of elements to mergesort() in main: merge_sort(a, 0, 10); which means r in merge sort should be excluded. The recursive call merge_sort(a, q + 1, r); in mergesort is then incorrect as q should be excluded in merge_sort(a, p, q); but included in the second half. Use merge_sort(a, q, r); instead.
you compute the middle of the segment with int q = (p + r) / 2;. You may have undefined behavior for large arrays as q + r may overflow the range of type int. This is a classic bug that can go unnoticed for decades until someone uses the code for a large array. Use int q = p + (r - p) / 2; to avoid it.
the algorithm in merge is incorrect: you assume that all values in the arrays are < 10000, which may be an invalid assumption. The code should handle all possible values. You should test the index variables to detect the end of the subarrays and handle the remaining values of the other array specifically.
you do not free the arrays allocated in merge, causing memory leaks.
to make it easier to change the element type, you could use a typedef.
Here is a improved version:
#include <stdio.h>
#ifdef USE_DOUBLE
typedef double sorttype;
#else
typedef int sorttype;
#endif
void merge(sorttype *a, int p, int q, int r) {
// merge subarrays a[p...q] and a[q...r]
// upper bounds q and r are excluded
int n1 = q - p;
int n2 = r - q;
sorttype *a1, *a2;
int i, j, k;
a1 = malloc(n1 * sizeof(*a1));
a2 = malloc(n2 * sizeof(*a2));
for (i = 0; i < n1; i++)
a1[i] = a[p + i];
for (j = 0; j < n2; j++)
a2[j] = a[q + j];
i = 0;
j = 0;
for (k = p; k < r; k++) {
if (i < n1 && (j >= n2 || a1[i] <= a2[j])) {
a[k] = a1[i];
++i;
} else {
a[k] = a2[j];
++j;
}
}
free(a1);
free(a2);
}
void merge_sort(sorttype *s, int p, int r) {
if (r - p > 1) {
int q = p + (r - p) / 2;
merge_sort(s, p, q);
merge_sort(s, q, r);
merge(s, p, q, r);
}
}
int main(int argc, char *argv[]) {
sorttype a[10];
int i;
for (i = 0; i < 10; i++) {
a[i] = 1 + rand() % 10;
}
merge_sort(a, 0, 10);
for (i = 0; i < 10; i++) {
#ifdef USE_DOUBLE
printf("%g ", a[i]);
#else
printf("%d ", a[i]);
#endif
}
printf("\n");
return 0;
}
Output for int:
1 3 4 4 5 8 9 9 10 10
Output for double:
1 3 4 4 5 8 9 9 10 10
Notice how the random numbers are identical although the program was recompiled and re-run... You should use srand(clock()) to try and get a different pseudo-random sequence.
Note also that allocating a2 to make a copy of the right subarray is not required because the merge operation never overwrites elements from the right half that have not already been copied.
Furthermore, you should test for allocation failure and report it.
Here is an improved version of merge:
void merge(sorttype *a, int p, int q, int r) {
// merge subarrays a[p...q] and a[q...r]
// upper bounds q and r are excluded
int n1 = q - p;
int n2 = r - q;
sorttype *a1;
int i, j, k;
a1 = malloc(n1 * sizeof(*a1));
if (a1 == NULL) {
fprintf(stderr, "memory allocation failure\n");
exit(1);
}
for (i = 0; i < n1; i++)
a1[i] = a[p + i];
i = 0;
j = 0;
for (k = p; i < n1 && k < r; k++) {
if (j >= n2 || a1[i] <= a[q + j]) {
a[k] = a1[i];
++i;
} else {
a[k] = a[q + j];
++j;
}
}
free(a1);
}
I've looked around online for an non-recursive k-combinations algorithm, but have had trouble understanding all of the reindexing involved; The code I've found online is not commented well, or crashes.
For example, if I have the collection, {'a', 'b', 'c', 'd', 'e'} and I want to find a 3 combinations; ie,
abc
abd
abe
acd
ace
ade
bcd
bce
bde
cde
How can I implement an algorithm to do this? When I write down the general procedure, this it is clear. That is; I increment the last element in a pointer until it points to 'e', increment the second to last element and set the last element to the second to last element + 1, then increment the last element again until it reaches 'e' again, and so on and so forth, as illustrated by how I printed the combinations. I looked at Algorithm to return all combinations of k elements from n for inspiration, but my code only prints 'abc'. Here is a copy of it:
#include <stdio.h>
#include <stdlib.h>
static void
comb(char *buf, int n, int m)
{
// Initialize a pointer representing the combinations
char *ptr = malloc(sizeof(char) * m);
int i, j, k;
for (i = 0; i < m; i++) ptr[i] = buf[i];
while (1) {
printf("%s\n", ptr);
j = m - 1;
i = 1;
// flag used to denote that the end substring is at it's max and
// the j-th indice must be incremented and all indices above it must
// be reset.
int iter_down = 0;
while((j >= 0) && !iter_down) {
//
if (ptr[j] < (n - i) ) {
iter_down = 1;
ptr[j]++;
for (k = j + 1; k < m; k++) {
ptr[k] = ptr[j] + (k - j);
}
}
else {
j--;
i++;
}
}
if (!iter_down) break;
}
}
int
main(void)
{
char *buf = "abcde";
comb(buf, 5, 3);
return 1;
}
The very big problem with your code is mixing up indices and values. You have an array of chars, but then you try to increment the chars as if they were indices into the buffer. What you really need is an array of indices. The array of chars can be discarded, since the indices provide all you need, or you can keep the array of chars separately.
I found a psuedocode description here, http://www4.uwsp.edu/math/nwodarz/Math209Files/209-0809F-L10-Section06_03-AlgorithmsForGeneratingPermutationsAndCombinations-Notes.pdf
and implemented it in C by
#include <stdlib.h>
#include <stdio.h>
// Prints an array of integers
static void
print_comb(int *val, int len) {
int i;
for (i = 0; i < len; i++) {
printf("%d ", val[i]);
}
printf("\n");
}
// Calculates n choose k
static int
choose(int n, int k)
{
double i, l = 1.0;
double val = 1.0;
for (i = 1.0; i <= k; i++) {
l = ((double)n + 1 - i) / i;
val *= l;
}
return (int) val;
}
static void
comb(int n, int r)
{
int i, j, m, max_val;
int s[r];
// Initialize combinations
for (i = 0; i < r; i++) {
s[i] = i;
}
print_comb(s, r);
// Iterate over the remaining space
for (i = 1; i < choose(n, r); i++) {
// use for indexing the rightmost element which is not at maximum value
m = r - 1;
// use as the maximum value at an index, specified by m
max_val = n - 1; // use for
while(s[m] == max_val) {
m--;
max_val--;
}
// increment the index which is not at it's maximum value
s[m]++;
// iterate over the elements after m increasing their value recursively
// ie if the m-th element is incremented, all elements afterwards are
// incremented by one plus it's offset from m
// For example, this is responsible for switching 0 3 4 to 1 2 3 in
// comb(5, 3) since 3 and 4 in the first combination are at their maximum
// value
for (j = m; j < r - 1; j++) {
s[j + 1] = s[j] + 1;
}
print_comb(s, r);
}
}
int
main(void)
{
comb(5, 3);
return 1;
}