2

I have a program that takes in a pyramid of people with weight values and is supposed to use a recursive function to add the weight of the two people that the person is supporting (if the person is on an edge of a pyramid they only are supporting one persons weight I included a picture encase I didn't explain this well enough) and add that to its own weight value. The problem I'm currently having is simply that the function itself is only taking in the first value of the 2D array instead of all the values? Pyramid Example

Code:

#include <stdio.h>

void weight(float x[100][100],int y, int z,int b)
{
    if(z==0&&y==0)
    {
        printf("%.2f\n",x[y][z]);
        weight(x,y+1,z,b);
        return;
    }
    if(z==0&&y==b)
    {
        printf("%.2f",x[y][z]);
        x[y][z]+=x[y-1][z];
        printf("%.2f",x[y][z]);

    }
    if(z==0&&y!=b)
    {
        x[y][z]+=x[y-1][z];
        printf("%.2f",x[y][z]);
        weight(x,y+1,z,b);
    }
    if(y==z&&y==b)
    {
        printf("%.2f",x[y][z]);
        x[y][z]+=x[y-1][z-1];
        return;
    }
    if(y==z&&y!=b)
    {

        x[y][z]+=x[y-1][z-1];
        printf("%.2f\n",x[y][z]);
        weight(x,y+1,0,b);
    }
    if(y!=z)
    {
        printf("%.2f",x[y][z]);
        x[y][z]+=x[y-1][z]+x[y-1][z-1];
    }

}


int main()
{

    //Initialize Variables for use within the program
    int bottom;
    int input;
    int counter=0;

    printf("How many people are in the bottom row of your pyramid: ");
    scanf("%d",&bottom);

    //Initializes pyramid array at correct length
    float pyramid[bottom][bottom];

    //Takes in all user given input values for pyramid weights
    for(int i=0;i<bottom;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("Please input the weight of person #%d: ",++counter);
            scanf("%f",&pyramid[i][j]);
        }
    }

    //Prints out all weight values based on user given input
    printf("Pyramid before weight distribution\n");
    for(int i=0; i<bottom;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%.2f ",pyramid[i][j]);
        }
        printf("\n");
    }

    //Prints out all weight values after supporting weight values have been added thru recursive function
    printf("Pyramid after weight distribution\n");
    weight(pyramid,0,0,bottom-1);

    return 0;
}
klutt
  • 30,332
  • 17
  • 55
  • 95
Bobert
  • 25
  • 7
  • Can you explain what you mean by "the function itself is only taking in the first value of the 2D array instead of all the values"? – Code-Apprentice Nov 07 '17 at 19:19
  • I don't think you should change the values in the 2D array. Instead, return a a value from the `weight()` function. – Code-Apprentice Nov 07 '17 at 19:20
  • `float pyramid[bottom][bottom]` and `float x[100][100]` don't match (if `bottom != 100`). – BLUEPIXY Nov 07 '17 at 19:20
  • What do you mean by "don't match"? Can you give an example? – Code-Apprentice Nov 07 '17 at 19:22
  • You pass in the indices (y and z) of the first array element to function weight, but weight never modifies those values to index the other elements in the array. – Jim Rogers Nov 07 '17 at 19:27
  • @BLUEPIXY So for the function to carry all values I have to make the parameters the same? – Bobert Nov 07 '17 at 19:32
  • @N.Sweeney Yes (For proper operation). See [this](https://stackoverflow.com/a/47134882/971127) – BLUEPIXY Nov 07 '17 at 19:35
  • Not to throw a wrench into your logic, but "*if the person is on an edge of a pyramid they only are supporting one persons weight*" isn't exactly true. If you look at a freebody diagram for each person, people on the edge support 1/2 of each above, e.g. `G` supports `D/2 + B/2 + A/2`. It has a cumulative effect with depth in the pyramid. – David C. Rankin Nov 07 '17 at 20:57

1 Answers1

3

There's one major mistake in your code. You cannot have a variable size on float pyramid[bottom][bottom] and then send it to a function accepting a float [100][100]. A quick fix for this is to just declare float pyramid[100][100] No matter the size of bottom.

As for the rest, I made three solutions. One solution fixes the pyramid without printouts, and you can print it afterwards. The reason is that it is much simpler. You do not have to worry about the recursive calls being in a specific order. After that there's one solution that calculates the weight of a given person. The last solution handles printouts inside the recursive function.

Code with relevant changes:

#include <stdio.h>

void weight(float w[100][100],int y, int x,int b)
{
    if(y<b) {
        float current = w[y][x];
        w[y+1][x] += current / 2;
        w[y+1][x+1] += current /2;
        weight(w, y+1, x, b);
        if(x==y)
            weight(w, y+1, x+1, b);
    }
}

int main()
{
    ...

    //Initializes pyramid array at correct length                                                                  
    float pyramid[100][100];

    ...

    // Transform pyramid into weighted pyramid
    weight(pyramid,0,0,bottom);

    //Prints out all weight values after supporting weight values have been added thru recursive function          
    printf("Pyramid after weight distribution\n");
    for(int i=0; i<bottom;i++)
    {
        for(int j=0;j<=i;j++)
        {
            printf("%.2f ",pyramid[i][j]);
        }
        printf("\n");
    }
}

I also took the liberty of dividing the weight by 2, for obvious reasons. I also changed the name of the variables to something a bit less confusing for me.

input.txt :

5 3 4 5 7 5 3 4 5 3 6 7 8 4 7 5

Output:

$ ./a.out < input.txt
Pyramid before weight distribution
3.00 
4.00 5.00 
7.00 5.00 3.00 
4.00 5.00 3.00 6.00 
7.00 8.00 4.00 7.00 5.00 
Pyramid after weight distribution
3.00 
5.50 6.50 
9.75 11.00 6.25 
8.88 15.38 11.62 9.12 
11.44 20.12 17.50 17.38 9.56 

An alternative recursive approach is to write a function that returns the total weight for a particular node. Looks like this:

float gweight(float w[100][100], int y, int x)
{
    float ret = w[y][x];

    if(y==0)
        return ret;
    if(x<y)
        ret +=  gweight(w, y-1, x) / 2;
    if(x>0)
        ret += gweight(w, y-1, x-1) / 2;
    return ret;
}

And then you can print the result with a similar loop as above, but change the print statement to: printf("%.2f ",gweight(pyramid, i, j))

The drawback of this method is that you will calculate the same value many more times. For huge pyramids it could greatly impact performance.

And finally, a version that actually does exactly what you want.

void weight(float w[100][100],int y, int x,int b)
{
    if(y==b)
        return;

    float current = w[y][x];

    printf("%.2f ", current);

    if(y<b) {
        w[y+1][x] += current / 2;
        w[y+1][x+1] += current /2;
    }

    if(y==x) {
        printf("\n");
        weight(w, y+1, 0, b);
    } else
        weight(w, y, x+1, b);
}
klutt
  • 30,332
  • 17
  • 55
  • 95
  • While not what is called for by the question, a non-recursive solution avoids the function call overhead generated by each recursive call. While for small pyramids, it doesn't matter, but for large computations it adds up. You can also replace the 2D array with a simple pointer to type and `realloc` as required. Good answer. – David C. Rankin Nov 08 '17 at 01:36
  • @DavidC.Rankin Yeah I thought about that too, but I also thought that would be a bit to far from the question. Was also considering dynamic allocation and pointers, but I settled for this. – klutt Nov 08 '17 at 01:39