Pair-wise difference using recursion











up vote
0
down vote

favorite












I was asked to translate this pseudo code into a C program:



rep := 0
while A not empty:
B :=
for x in A, y in A:
if x != y: append absolute_value(x - y) to B
A := B
rep := rep + 1


and I end up with this:



int iterateIt(int a_count, int* a) {
unsigned long long i, j, k;
unsigned long long count = a_count;

for( i = 1 ; i < a_count ; i++ )
count *= count-1;

int *b = (int *) malloc(count * sizeof(int));
count = 0;
k = 0;
for( i = 0 ; i < a_count ; i++ ){
for( j = i ; j < a_count ; j++ ){
if(a[i] != a[j]){
b[k] = abs(a[i] - a[j]);
k++;
}
}
}

if( k > 0){
return 1 + iterateIt(k, b);
}
free(b);
return 1;
}


I used recursion to return the number of iteration of the algorithm. Practically I take the difference between any two different objects of A and put the absolute value in B, on which I recur.
For simple input I get the correct result but I don't understand why for input like:
16 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768
or 4 1 352 9483 50000
(the first number is the number of element of A)



I get a segmentation fault error.



Thank you for your help










share|improve this question


















  • 1




    Why do you put count *= count-1; in a loop? What does it compute?
    – n.m.
    yesterday










  • You do not test the return value of malloc(). My guess would be that you are computing a huge or even negative (because overflow) value in count, malloc() is therefore failing, and you are then attempting to write through the resulting null pointer.
    – John Bollinger
    yesterday










  • Do you use an IDE? Does it have a debugger? Do you know how to use it? It is your best friend and will easilly let you resolve problems like this without having to ask us
    – Mawg
    yesterday















up vote
0
down vote

favorite












I was asked to translate this pseudo code into a C program:



rep := 0
while A not empty:
B :=
for x in A, y in A:
if x != y: append absolute_value(x - y) to B
A := B
rep := rep + 1


and I end up with this:



int iterateIt(int a_count, int* a) {
unsigned long long i, j, k;
unsigned long long count = a_count;

for( i = 1 ; i < a_count ; i++ )
count *= count-1;

int *b = (int *) malloc(count * sizeof(int));
count = 0;
k = 0;
for( i = 0 ; i < a_count ; i++ ){
for( j = i ; j < a_count ; j++ ){
if(a[i] != a[j]){
b[k] = abs(a[i] - a[j]);
k++;
}
}
}

if( k > 0){
return 1 + iterateIt(k, b);
}
free(b);
return 1;
}


I used recursion to return the number of iteration of the algorithm. Practically I take the difference between any two different objects of A and put the absolute value in B, on which I recur.
For simple input I get the correct result but I don't understand why for input like:
16 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768
or 4 1 352 9483 50000
(the first number is the number of element of A)



I get a segmentation fault error.



Thank you for your help










share|improve this question


















  • 1




    Why do you put count *= count-1; in a loop? What does it compute?
    – n.m.
    yesterday










  • You do not test the return value of malloc(). My guess would be that you are computing a huge or even negative (because overflow) value in count, malloc() is therefore failing, and you are then attempting to write through the resulting null pointer.
    – John Bollinger
    yesterday










  • Do you use an IDE? Does it have a debugger? Do you know how to use it? It is your best friend and will easilly let you resolve problems like this without having to ask us
    – Mawg
    yesterday













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I was asked to translate this pseudo code into a C program:



rep := 0
while A not empty:
B :=
for x in A, y in A:
if x != y: append absolute_value(x - y) to B
A := B
rep := rep + 1


and I end up with this:



int iterateIt(int a_count, int* a) {
unsigned long long i, j, k;
unsigned long long count = a_count;

for( i = 1 ; i < a_count ; i++ )
count *= count-1;

int *b = (int *) malloc(count * sizeof(int));
count = 0;
k = 0;
for( i = 0 ; i < a_count ; i++ ){
for( j = i ; j < a_count ; j++ ){
if(a[i] != a[j]){
b[k] = abs(a[i] - a[j]);
k++;
}
}
}

if( k > 0){
return 1 + iterateIt(k, b);
}
free(b);
return 1;
}


I used recursion to return the number of iteration of the algorithm. Practically I take the difference between any two different objects of A and put the absolute value in B, on which I recur.
For simple input I get the correct result but I don't understand why for input like:
16 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768
or 4 1 352 9483 50000
(the first number is the number of element of A)



I get a segmentation fault error.



Thank you for your help










share|improve this question













I was asked to translate this pseudo code into a C program:



rep := 0
while A not empty:
B :=
for x in A, y in A:
if x != y: append absolute_value(x - y) to B
A := B
rep := rep + 1


and I end up with this:



int iterateIt(int a_count, int* a) {
unsigned long long i, j, k;
unsigned long long count = a_count;

for( i = 1 ; i < a_count ; i++ )
count *= count-1;

int *b = (int *) malloc(count * sizeof(int));
count = 0;
k = 0;
for( i = 0 ; i < a_count ; i++ ){
for( j = i ; j < a_count ; j++ ){
if(a[i] != a[j]){
b[k] = abs(a[i] - a[j]);
k++;
}
}
}

if( k > 0){
return 1 + iterateIt(k, b);
}
free(b);
return 1;
}


I used recursion to return the number of iteration of the algorithm. Practically I take the difference between any two different objects of A and put the absolute value in B, on which I recur.
For simple input I get the correct result but I don't understand why for input like:
16 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768
or 4 1 352 9483 50000
(the first number is the number of element of A)



I get a segmentation fault error.



Thank you for your help







c arrays recursion segmentation-fault






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









Andrea Foderaro

56




56








  • 1




    Why do you put count *= count-1; in a loop? What does it compute?
    – n.m.
    yesterday










  • You do not test the return value of malloc(). My guess would be that you are computing a huge or even negative (because overflow) value in count, malloc() is therefore failing, and you are then attempting to write through the resulting null pointer.
    – John Bollinger
    yesterday










  • Do you use an IDE? Does it have a debugger? Do you know how to use it? It is your best friend and will easilly let you resolve problems like this without having to ask us
    – Mawg
    yesterday














  • 1




    Why do you put count *= count-1; in a loop? What does it compute?
    – n.m.
    yesterday










  • You do not test the return value of malloc(). My guess would be that you are computing a huge or even negative (because overflow) value in count, malloc() is therefore failing, and you are then attempting to write through the resulting null pointer.
    – John Bollinger
    yesterday










  • Do you use an IDE? Does it have a debugger? Do you know how to use it? It is your best friend and will easilly let you resolve problems like this without having to ask us
    – Mawg
    yesterday








1




1




Why do you put count *= count-1; in a loop? What does it compute?
– n.m.
yesterday




Why do you put count *= count-1; in a loop? What does it compute?
– n.m.
yesterday












You do not test the return value of malloc(). My guess would be that you are computing a huge or even negative (because overflow) value in count, malloc() is therefore failing, and you are then attempting to write through the resulting null pointer.
– John Bollinger
yesterday




You do not test the return value of malloc(). My guess would be that you are computing a huge or even negative (because overflow) value in count, malloc() is therefore failing, and you are then attempting to write through the resulting null pointer.
– John Bollinger
yesterday












Do you use an IDE? Does it have a debugger? Do you know how to use it? It is your best friend and will easilly let you resolve problems like this without having to ask us
– Mawg
yesterday




Do you use an IDE? Does it have a debugger? Do you know how to use it? It is your best friend and will easilly let you resolve problems like this without having to ask us
– Mawg
yesterday












2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted










I think your count is wrong. Your second iteration is already humongous.



#include <stdio.h>
#include <stdlib.h>

size_t total_allocated = 0;

int iterateIt(int a_count, int* a) {
unsigned long long i, j, k;
unsigned long long count = a_count;

for( i = 1 ; i < a_count ; i++ )
count *= count-1;

size_t size = count * sizeof(int);
printf("Allocating %llu ints: %llu bytesn", count, (unsigned long long)size);
total_allocated += size;
printf("Total allocated: %llu bytesn", (unsigned long long)total_allocated);
int *b = (int *) malloc(count * sizeof(int));
count = 0;
k = 0;
for( i = 0 ; i < a_count ; i++ ){
for( j = i ; j < a_count ; j++ ){
if(a[i] != a[j]){
b[k] = abs(a[i] - a[j]);
k++;
}
}
}

if( k > 0){
return 1 + iterateIt(k, b);
}
free(b);
return 1;
}

int main (void)
{
iterateIt(4, (int[4]){1,352,9483,50000});
return 0;
}


Result:



Allocating 17292 ints: 69168 bytes
Total allocated: 69168 bytes
Allocating 12550317587327992670 ints: 13307782201892867448 bytes
Total allocated: 13307782201892936616 bytes





share|improve this answer




























    up vote
    1
    down vote













    First consider this line:



    return 1 + iterateIt(k, b);


    The b array never gets freed on this return but if k is zero, it does. Let's rewrite this code to clean it up a bit:



    #include <stdio.h>
    #include <stdlib.h>

    unsigned iterateIt(size_t a_count, int *a) {

    unsigned rep = 1;

    int *b = calloc(a_count * a_count, sizeof(int));

    size_t k = 0;

    for (size_t i = 0; i < a_count; i++) {
    for (size_t j = i + 1; j < a_count; j++) {
    if (a[i] != a[j]) {
    b[k++] = abs(a[i] - a[j]);
    }
    }
    }

    if (k > 0) {
    rep += iterateIt(k, b);
    }

    free(b);

    return rep;
    }

    int main() {

    int x = {1, 324, 54};

    printf("%un", iterateIt(sizeof(x) / sizeof(int), x));

    return 0;
    }


    Watching the value of a_count, the program tries to allocate too much memory and fails.



    UPDATE



    Since the two halves of the matrix end up identical, I fixed the above code to do what the OP did, just process 1/2 the matrix, i.e. j starts at i + 1 since the two halves end up identical. I also ignore the diagonal as it's always zeros. Then the code completes for the three numbers in my example code but blows up again when I increase the array to four values.



    I believe the recursive nature of the OP's solution is elegant and a non-issue but just to confirm, here's an iterative solution that fails to perform and not due to lack of stack memory:



    unsigned iterateIt(size_t a_count, int *a) {

    unsigned rep = 1;

    bool first_time = true;

    while (true) {

    int *b = calloc((a_count * a_count) / 2, sizeof(int));

    if (b == NULL) {
    perror("calloc failed!");
    exit(1);
    }

    size_t b_count = 0;

    for (size_t i = 0; i < a_count; i++) {
    for (size_t j = i + 1; j < a_count; j++) {
    if (a[i] != a[j]) {
    b[b_count ++] = abs(a[i] - a[j]);
    }
    }
    }

    if (b_count == 0) {
    free(b);
    break;
    }

    if (first_time) {
    first_time = false;
    } else {
    free(a);
    }

    a = b;
    a_count = b_count;

    rep++;
    }

    return rep;
    }





    share|improve this answer























    • The convergence is definitely there: at each round the maximal value decreases. I don't see a reason for a recursive approach though.
      – user58697
      yesterday











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416987%2fpair-wise-difference-using-recursion%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote



    accepted










    I think your count is wrong. Your second iteration is already humongous.



    #include <stdio.h>
    #include <stdlib.h>

    size_t total_allocated = 0;

    int iterateIt(int a_count, int* a) {
    unsigned long long i, j, k;
    unsigned long long count = a_count;

    for( i = 1 ; i < a_count ; i++ )
    count *= count-1;

    size_t size = count * sizeof(int);
    printf("Allocating %llu ints: %llu bytesn", count, (unsigned long long)size);
    total_allocated += size;
    printf("Total allocated: %llu bytesn", (unsigned long long)total_allocated);
    int *b = (int *) malloc(count * sizeof(int));
    count = 0;
    k = 0;
    for( i = 0 ; i < a_count ; i++ ){
    for( j = i ; j < a_count ; j++ ){
    if(a[i] != a[j]){
    b[k] = abs(a[i] - a[j]);
    k++;
    }
    }
    }

    if( k > 0){
    return 1 + iterateIt(k, b);
    }
    free(b);
    return 1;
    }

    int main (void)
    {
    iterateIt(4, (int[4]){1,352,9483,50000});
    return 0;
    }


    Result:



    Allocating 17292 ints: 69168 bytes
    Total allocated: 69168 bytes
    Allocating 12550317587327992670 ints: 13307782201892867448 bytes
    Total allocated: 13307782201892936616 bytes





    share|improve this answer

























      up vote
      1
      down vote



      accepted










      I think your count is wrong. Your second iteration is already humongous.



      #include <stdio.h>
      #include <stdlib.h>

      size_t total_allocated = 0;

      int iterateIt(int a_count, int* a) {
      unsigned long long i, j, k;
      unsigned long long count = a_count;

      for( i = 1 ; i < a_count ; i++ )
      count *= count-1;

      size_t size = count * sizeof(int);
      printf("Allocating %llu ints: %llu bytesn", count, (unsigned long long)size);
      total_allocated += size;
      printf("Total allocated: %llu bytesn", (unsigned long long)total_allocated);
      int *b = (int *) malloc(count * sizeof(int));
      count = 0;
      k = 0;
      for( i = 0 ; i < a_count ; i++ ){
      for( j = i ; j < a_count ; j++ ){
      if(a[i] != a[j]){
      b[k] = abs(a[i] - a[j]);
      k++;
      }
      }
      }

      if( k > 0){
      return 1 + iterateIt(k, b);
      }
      free(b);
      return 1;
      }

      int main (void)
      {
      iterateIt(4, (int[4]){1,352,9483,50000});
      return 0;
      }


      Result:



      Allocating 17292 ints: 69168 bytes
      Total allocated: 69168 bytes
      Allocating 12550317587327992670 ints: 13307782201892867448 bytes
      Total allocated: 13307782201892936616 bytes





      share|improve this answer























        up vote
        1
        down vote



        accepted







        up vote
        1
        down vote



        accepted






        I think your count is wrong. Your second iteration is already humongous.



        #include <stdio.h>
        #include <stdlib.h>

        size_t total_allocated = 0;

        int iterateIt(int a_count, int* a) {
        unsigned long long i, j, k;
        unsigned long long count = a_count;

        for( i = 1 ; i < a_count ; i++ )
        count *= count-1;

        size_t size = count * sizeof(int);
        printf("Allocating %llu ints: %llu bytesn", count, (unsigned long long)size);
        total_allocated += size;
        printf("Total allocated: %llu bytesn", (unsigned long long)total_allocated);
        int *b = (int *) malloc(count * sizeof(int));
        count = 0;
        k = 0;
        for( i = 0 ; i < a_count ; i++ ){
        for( j = i ; j < a_count ; j++ ){
        if(a[i] != a[j]){
        b[k] = abs(a[i] - a[j]);
        k++;
        }
        }
        }

        if( k > 0){
        return 1 + iterateIt(k, b);
        }
        free(b);
        return 1;
        }

        int main (void)
        {
        iterateIt(4, (int[4]){1,352,9483,50000});
        return 0;
        }


        Result:



        Allocating 17292 ints: 69168 bytes
        Total allocated: 69168 bytes
        Allocating 12550317587327992670 ints: 13307782201892867448 bytes
        Total allocated: 13307782201892936616 bytes





        share|improve this answer












        I think your count is wrong. Your second iteration is already humongous.



        #include <stdio.h>
        #include <stdlib.h>

        size_t total_allocated = 0;

        int iterateIt(int a_count, int* a) {
        unsigned long long i, j, k;
        unsigned long long count = a_count;

        for( i = 1 ; i < a_count ; i++ )
        count *= count-1;

        size_t size = count * sizeof(int);
        printf("Allocating %llu ints: %llu bytesn", count, (unsigned long long)size);
        total_allocated += size;
        printf("Total allocated: %llu bytesn", (unsigned long long)total_allocated);
        int *b = (int *) malloc(count * sizeof(int));
        count = 0;
        k = 0;
        for( i = 0 ; i < a_count ; i++ ){
        for( j = i ; j < a_count ; j++ ){
        if(a[i] != a[j]){
        b[k] = abs(a[i] - a[j]);
        k++;
        }
        }
        }

        if( k > 0){
        return 1 + iterateIt(k, b);
        }
        free(b);
        return 1;
        }

        int main (void)
        {
        iterateIt(4, (int[4]){1,352,9483,50000});
        return 0;
        }


        Result:



        Allocating 17292 ints: 69168 bytes
        Total allocated: 69168 bytes
        Allocating 12550317587327992670 ints: 13307782201892867448 bytes
        Total allocated: 13307782201892936616 bytes






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered yesterday









        contrapants

        38916




        38916
























            up vote
            1
            down vote













            First consider this line:



            return 1 + iterateIt(k, b);


            The b array never gets freed on this return but if k is zero, it does. Let's rewrite this code to clean it up a bit:



            #include <stdio.h>
            #include <stdlib.h>

            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            int *b = calloc(a_count * a_count, sizeof(int));

            size_t k = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[k++] = abs(a[i] - a[j]);
            }
            }
            }

            if (k > 0) {
            rep += iterateIt(k, b);
            }

            free(b);

            return rep;
            }

            int main() {

            int x = {1, 324, 54};

            printf("%un", iterateIt(sizeof(x) / sizeof(int), x));

            return 0;
            }


            Watching the value of a_count, the program tries to allocate too much memory and fails.



            UPDATE



            Since the two halves of the matrix end up identical, I fixed the above code to do what the OP did, just process 1/2 the matrix, i.e. j starts at i + 1 since the two halves end up identical. I also ignore the diagonal as it's always zeros. Then the code completes for the three numbers in my example code but blows up again when I increase the array to four values.



            I believe the recursive nature of the OP's solution is elegant and a non-issue but just to confirm, here's an iterative solution that fails to perform and not due to lack of stack memory:



            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            bool first_time = true;

            while (true) {

            int *b = calloc((a_count * a_count) / 2, sizeof(int));

            if (b == NULL) {
            perror("calloc failed!");
            exit(1);
            }

            size_t b_count = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[b_count ++] = abs(a[i] - a[j]);
            }
            }
            }

            if (b_count == 0) {
            free(b);
            break;
            }

            if (first_time) {
            first_time = false;
            } else {
            free(a);
            }

            a = b;
            a_count = b_count;

            rep++;
            }

            return rep;
            }





            share|improve this answer























            • The convergence is definitely there: at each round the maximal value decreases. I don't see a reason for a recursive approach though.
              – user58697
              yesterday















            up vote
            1
            down vote













            First consider this line:



            return 1 + iterateIt(k, b);


            The b array never gets freed on this return but if k is zero, it does. Let's rewrite this code to clean it up a bit:



            #include <stdio.h>
            #include <stdlib.h>

            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            int *b = calloc(a_count * a_count, sizeof(int));

            size_t k = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[k++] = abs(a[i] - a[j]);
            }
            }
            }

            if (k > 0) {
            rep += iterateIt(k, b);
            }

            free(b);

            return rep;
            }

            int main() {

            int x = {1, 324, 54};

            printf("%un", iterateIt(sizeof(x) / sizeof(int), x));

            return 0;
            }


            Watching the value of a_count, the program tries to allocate too much memory and fails.



            UPDATE



            Since the two halves of the matrix end up identical, I fixed the above code to do what the OP did, just process 1/2 the matrix, i.e. j starts at i + 1 since the two halves end up identical. I also ignore the diagonal as it's always zeros. Then the code completes for the three numbers in my example code but blows up again when I increase the array to four values.



            I believe the recursive nature of the OP's solution is elegant and a non-issue but just to confirm, here's an iterative solution that fails to perform and not due to lack of stack memory:



            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            bool first_time = true;

            while (true) {

            int *b = calloc((a_count * a_count) / 2, sizeof(int));

            if (b == NULL) {
            perror("calloc failed!");
            exit(1);
            }

            size_t b_count = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[b_count ++] = abs(a[i] - a[j]);
            }
            }
            }

            if (b_count == 0) {
            free(b);
            break;
            }

            if (first_time) {
            first_time = false;
            } else {
            free(a);
            }

            a = b;
            a_count = b_count;

            rep++;
            }

            return rep;
            }





            share|improve this answer























            • The convergence is definitely there: at each round the maximal value decreases. I don't see a reason for a recursive approach though.
              – user58697
              yesterday













            up vote
            1
            down vote










            up vote
            1
            down vote









            First consider this line:



            return 1 + iterateIt(k, b);


            The b array never gets freed on this return but if k is zero, it does. Let's rewrite this code to clean it up a bit:



            #include <stdio.h>
            #include <stdlib.h>

            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            int *b = calloc(a_count * a_count, sizeof(int));

            size_t k = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[k++] = abs(a[i] - a[j]);
            }
            }
            }

            if (k > 0) {
            rep += iterateIt(k, b);
            }

            free(b);

            return rep;
            }

            int main() {

            int x = {1, 324, 54};

            printf("%un", iterateIt(sizeof(x) / sizeof(int), x));

            return 0;
            }


            Watching the value of a_count, the program tries to allocate too much memory and fails.



            UPDATE



            Since the two halves of the matrix end up identical, I fixed the above code to do what the OP did, just process 1/2 the matrix, i.e. j starts at i + 1 since the two halves end up identical. I also ignore the diagonal as it's always zeros. Then the code completes for the three numbers in my example code but blows up again when I increase the array to four values.



            I believe the recursive nature of the OP's solution is elegant and a non-issue but just to confirm, here's an iterative solution that fails to perform and not due to lack of stack memory:



            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            bool first_time = true;

            while (true) {

            int *b = calloc((a_count * a_count) / 2, sizeof(int));

            if (b == NULL) {
            perror("calloc failed!");
            exit(1);
            }

            size_t b_count = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[b_count ++] = abs(a[i] - a[j]);
            }
            }
            }

            if (b_count == 0) {
            free(b);
            break;
            }

            if (first_time) {
            first_time = false;
            } else {
            free(a);
            }

            a = b;
            a_count = b_count;

            rep++;
            }

            return rep;
            }





            share|improve this answer














            First consider this line:



            return 1 + iterateIt(k, b);


            The b array never gets freed on this return but if k is zero, it does. Let's rewrite this code to clean it up a bit:



            #include <stdio.h>
            #include <stdlib.h>

            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            int *b = calloc(a_count * a_count, sizeof(int));

            size_t k = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[k++] = abs(a[i] - a[j]);
            }
            }
            }

            if (k > 0) {
            rep += iterateIt(k, b);
            }

            free(b);

            return rep;
            }

            int main() {

            int x = {1, 324, 54};

            printf("%un", iterateIt(sizeof(x) / sizeof(int), x));

            return 0;
            }


            Watching the value of a_count, the program tries to allocate too much memory and fails.



            UPDATE



            Since the two halves of the matrix end up identical, I fixed the above code to do what the OP did, just process 1/2 the matrix, i.e. j starts at i + 1 since the two halves end up identical. I also ignore the diagonal as it's always zeros. Then the code completes for the three numbers in my example code but blows up again when I increase the array to four values.



            I believe the recursive nature of the OP's solution is elegant and a non-issue but just to confirm, here's an iterative solution that fails to perform and not due to lack of stack memory:



            unsigned iterateIt(size_t a_count, int *a) {

            unsigned rep = 1;

            bool first_time = true;

            while (true) {

            int *b = calloc((a_count * a_count) / 2, sizeof(int));

            if (b == NULL) {
            perror("calloc failed!");
            exit(1);
            }

            size_t b_count = 0;

            for (size_t i = 0; i < a_count; i++) {
            for (size_t j = i + 1; j < a_count; j++) {
            if (a[i] != a[j]) {
            b[b_count ++] = abs(a[i] - a[j]);
            }
            }
            }

            if (b_count == 0) {
            free(b);
            break;
            }

            if (first_time) {
            first_time = false;
            } else {
            free(a);
            }

            a = b;
            a_count = b_count;

            rep++;
            }

            return rep;
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            cdlane

            16.5k21042




            16.5k21042












            • The convergence is definitely there: at each round the maximal value decreases. I don't see a reason for a recursive approach though.
              – user58697
              yesterday


















            • The convergence is definitely there: at each round the maximal value decreases. I don't see a reason for a recursive approach though.
              – user58697
              yesterday
















            The convergence is definitely there: at each round the maximal value decreases. I don't see a reason for a recursive approach though.
            – user58697
            yesterday




            The convergence is definitely there: at each round the maximal value decreases. I don't see a reason for a recursive approach though.
            – user58697
            yesterday


















             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416987%2fpair-wise-difference-using-recursion%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            What visual should I use to simply compare current year value vs last year in Power BI desktop

            How to ignore python UserWarning in pytest?

            Alexandru Averescu