Create a Hosoya's Triangle in java

蹲街弑〆低调 提交于 2021-01-29 04:15:00

问题


So I'm trying to create a Hosoya's Triangle in Java, and I'm running into some math issues. I have started by making an empty 2D array that has a user input # of levels:

int[][] tri = new int[levels][];
    //build the empty triangle
    for (int row =0;row< tri.length;row++){
        tri[row] = new int[row+1];
    }

this part is functional. The problem I'm having is in the next part, where I try to fill the triangle with Fibonacci numbers (I add the previous chunk of code because I'm thinking maybe building this array in a different way would help). I tried making the first few numbers outside the loop and just set them to 1, and then start actually looping at tri[2][0], which is the 3rd row. I've seen the equations on the wiki page of how to calculate each number, but I keep throwing index out of bounds errors when it tries to access something like tri[0][1].

for (int x=2;x<15;x++){ //TODO replace 15 with variable value
        for (int y=0;y<15;y++){
            tri[x][y] = tri[x-1][y] + tri[x-2][y];
        }

the 15 is just an arbitrary number, so that it would loop for every number in the triangle. I've been testing with 5 levels so 15 works for that. I was planning to fix that later.

I'm mostly just having trouble wrapping my head around the math of it and the relationships between each number in the triangle. There is another question that's basically the same here but the answer given didn't really make sense to me, and it hasn't been touched in 3 years so here I am.

There's another question here from last year that never got answered, and I'm thinking maybe they have the right idea: maybe i should build the left and right sides of the triangle first with different math and then fill in the middle with a separate loop, making 3 in all. I'm really unsure though, and I don't really have a clue where to go next. Side note: the assignment says I only have to print the triangle recursively, but if building it with recursive methods would be the best way I'm willing to hear any ideas.

The whole idea of recursion and the triangle itself are kind of confusing to me so I would really appreciate if you explain answers really thoroughly, I'm kind of struggling to catch up in this class. Thanks!


回答1:


First of all, it's harder to see the math with the format provided on the Wiki page of Hosoya's triangle. Let's take the first 5 rows:

             1
          1     1
       2     1     2
    3     2     2     3
 5     3     4     3     5

and re-arrange them to look like this:

 1
 1     1
 2     1     2
 3     2     2     3
 5     3     4     3     5

and you could probably see the pattern now:

starting from the 3rd row:
    for every number in the row
        if the number has a number above it (i.e. all except the last number in each row)
            it's the sum of the two numbers straight above it: H(n,j) = H(n-1,j) + H(n-2,j)
        otherwise (i.e. the last number in each row)
            it's the sum of the two numbers above it in the left diagonal: H(n,j) = H(n-1,j-1) + H(n-2),j-2)

The re-formatted numbers can be stored in a 2D array as shown. Then all we need to do is to print it out with proper spaces so it looks like the demonstration displayed on the Wiki page:

public class HosoyaTriangle {
    public static void main(String args[]) {
        final int N = 10;
        int[][] triangle = new int[N][N]; // this would initialize all cell elements to be 0

        //populate the base cases for the first two rows
        //H(0,0) = H(1,0) = H(1,1) = 1
        triangle[0][0] = triangle[1][0] = triangle[1][1] = 1;

        //starting from the 3rd row
        for (int row = 2; row < N; row++) {
            for (int col = 0; col < N; col++) {
                if (col < row) {
                    //H(n,j) = H(n-1,j) + H(n-2,j)
                    triangle[row][col] = triangle[row - 1][col] + triangle[row - 2][col];
                } else {
                    //H(n,j) = H(n-1,j-1) + H(n-2),j-2)
                    triangle[row][col] = triangle[row - 1][col - 1] + triangle[row - 2][col - 2];
                }
            }
        }
        print(triangle);
    }

    private static void print(int[][] matrix) {
        final int level = matrix.length;
        int spaceCount;
        StringBuilder sb;
        for (int row = 0; row < level; row++) {
            sb = new StringBuilder();

            //figure out how many spaces need to be printed before    
            //printing out the first non-zero number in the row
            spaceCount = level - row - 1;

            //add the spaces
            while(spaceCount-- > 0) {
                sb.append("  ");
            }
            //add all the non-zero numbers in the row
            for (int col = 0; col < level; col++) {
                if (matrix[row][col] > 0) {
                    sb.append(String.format("%4d",matrix[row][col]));
                }
            }
            System.out.println(sb.toString());
        }
    }
}

Output:

                     1
                   1   1
                 2   1   2
               3   2   2   3
             5   3   4   3   5
           8   5   6   6   5   8
        13   8  10   9  10   8  13
      21  13  16  15  15  16  13  21
    34  21  26  24  25  24  26  21  34
  55  34  42  39  40  40  39  42  34  55

EDIT:

Realized you're looking for a recursive solution. Given each number is calculated by the numbers in rows above, we can employ the same logic of fibonacci sequence and start from the Nth row, and recursively propagate upwards util we hit the base cases:

public static void main(String args[]) {
    final int N = 10;
    int[][] triangle = new int[N][N]; // this would initialize all cell elements to be 0

    //only need to loop through the last row
    //each column is calculated as a separate fibonacci sequence
    for (int col = N - 1; col >= 0; col--) {
        calc(N - 1, col, triangle);
    }
    print(triangle);
}

private static int calc(int row, int col, int[][] triangle) {
    //base cases
    if (row == 0 && col == 0 || row == 1 && col == 0 || row == 1 && col == 1 || row == 2 && col == 1) {
        triangle[row][col] = 1;

    } else {
        if (col < row) {
            //H(n,j) = H(n-1,j) + H(n-2,j)
            triangle[row][col] = calc(row - 1, col, triangle) + calc(row - 2, col, triangle);
        } else if (col == row) {
            //H(n,j) = H(n-1,j-1) + H(n-2),j-2)
            triangle[row][col] = calc(row - 1, col - 1, triangle) + calc(row - 2, col - 2, triangle);
        }
    }
    return triangle[row][col];
}

Note that this solution is much slower than the non-recursive one.



来源:https://stackoverflow.com/questions/36275039/create-a-hosoyas-triangle-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!