Convert negative index to positive index in an array (Trinomial Triangle) - java

I am trying to find trinomial coefficients and I want to avoid using negative index in my array. There will be instances whereby i or j will become negative and will return array out of bounds error. Is there anyway I can mirror the array contained in the negative indexes to a positive index?
Here’s the recursive formula: Recursion Formula
I recognize that T(0, -1) = T(0, 1) but how do I implement it?
example:
row 0: T(0, 0) = 1 , T(0, 1) = 0 ...
row 1: T(1, 0) = T(0, -1) + T(0, 0) + T(0, 1) , T(2, 0) ...
The trinomial coefficient T(n,k) is the coefficient of x^(n+k) in the expansion of (1+x+x^2)^n.
Trinomial triangle (middle index is 0, negative on the left of 0, positive on the right of 0):
Note: The code below iterates through the array from middle index 0 to the right.
public class ClassNameHere {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int k = Integer.parseInt(args[1]);
long[][] DP = new long[n + 1][k + 1];
DP[0][0] = 1;
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= Math.min(i, k); j++) {
if (i == j || ((j == 0) && i < 2)) DP[i][j] = 1;
else if (j < -i) {
DP[i][j] = 0;
} else DP[i][j] = DP[i - 1][j];
}
}
System.out.println(DP[n][k]);
}
}
Now I am able to get the terms from T(0, 0) to T(1, 0) with my code but unable to continue past T(2, 0) onwards by adding T(1,0) + T(1, 1) + T(1, 2). When I tried to implement DP[i][j] = DP[i - 1][j - 1] + DP[i - 1][j] + DP[i - 1][j + 1], it returns ArrayIndexOutOfBoundsException again.. I think that something is wrong with the implementation of the above statement ^. Any suggestions on how to go on with this?

You can populate such an array as follows: first create a new empty array with height n and width 2n+1, filled with zeros, and set the first entry at the upper midpoint to 1, then iterate over the rows and columns and set the other entries, each equal to the sum of the three entries above it:
T[i][j] = T[i-1][j-1] + T[i-1][j] + T[i-1][j+1];
Code:
int n = 7;
// new array filled with zeros
int[][] arr = new int[n][2 * n + 1];
// first entry
arr[0][n] = 1;
// iterate over the rows of the array
// starting from the second
for (int i = 1; i < arr.length; i++) {
// iterate over the columns of the array
// from the second to the penultimate
for (int j = 1; j < arr[i].length - 1; j++) {
// each entry is the sum of the three entries above it
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j] + arr[i - 1][j + 1];
}
}
// output
for (int[] row : arr) {
for (int cell : row)
if (cell > 0)
System.out.printf("%3d ", cell);
else
System.out.print(" ");
System.out.println();
}
Output:
1
1 1 1
1 2 3 2 1
1 3 6 7 6 3 1
1 4 10 16 19 16 10 4 1
1 5 15 30 45 51 45 30 15 5 1
1 6 21 50 90 126 141 126 90 50 21 6 1
See also: Finding trinomial coefficients using dynamic programming

I have found the cause.
It can be done by initializing the correct length in the 2D array.
long[][] tri = new long[n + 1][k + n + 1];
and using Math.abs() to handle instances where j index will flow to negative indices.
tri[i][j] = tri[i - 1][Math.abs(j - 1)] + tri[i - 1][j] + tri[i - 1][j + 1];

Related

How to print all the diagonals of a matrix in Java

I'm trying to figure out how to print an NxN matrix diagonally. Right now I can print the left to right diagonal but not the right to left.
So let's say the matrix is:
1 2 3
4 5 6
7 8 9
Now I can print left to right:
1
4 2
7 5 3
8 6
9
But I want also to print right to left:
3
6 2
9 5 1
8 4
7
Here is the code for left to right:
public static void printLeftToRightDiagonal(int[][] matrix) {
int length = matrix.length;
int diagonalLines = (length + length) - 1;
int itemsInDiagonal = 0;
int midPoint = (diagonalLines / 2) + 1;
for (int i = 1; i <= diagonalLines; i++) {
int rowIndex;
int columnIndex;
if (i <= midPoint) {
itemsInDiagonal++;
for (int j = 0; j < itemsInDiagonal; j++) {
rowIndex = (i - j) - 1;
columnIndex = j;
System.out.print(matrix[rowIndex][columnIndex] + " ");
}
} else {
itemsInDiagonal--;
for (int j = 0; j < itemsInDiagonal; j++) {
rowIndex = (length - 1) - j;
columnIndex = (i - length) + j;
System.out.print(matrix[rowIndex][columnIndex] + " ");
}
}
System.out.println();
}
}
I tried to figure out the pattern but I was left without ideas
The problem can be divided into two tasks:
print one reverse diagonal starting from a generic matrix[i, j] element, basically decrementing i and j by 1 in every cycle if both i and j are >= 0, otherwise ending the cycle.
identifying the starting matrix[i, j] elements and print the reverse diagonal starting from them.
The first rule is equivalent to write a method like below:
//example for matrix[2, 2] it will print 9 5 1
private static void printReverseDiagonal(int[][] matrix, int i, int j) {
System.out.print(matrix[i][j]);
for (int row = i - 1, column = j - 1; row >= 0 && column >= 0; --row, --column) {
System.out.print(" " + matrix[row][column]);
}
System.out.println();
}
The second rule is equivalent to write one cycle iterating over elements matrix[0, n - 1], matrix[1, n - 1] ... matrix[n - 1, n - 1] and another one iterating over elements matrix[n - 2, n - 1], matrix[n - 3, n - 1] .... matrix[0, n - 1] like below:
public static void printRightToLeftDiagonal(int[][] matrix) {
int n = matrix.length;
int j = n - 1;
for (int i = 0; i < n; ++i) {
printReverseDiagonal(matrix, i, j);
}
int i = n - 1;
for(j = n - 2; j >= 0; --j) {
printReverseDiagonal(matrix, i, j);
}
}
Combining the two functions you obtain your expected result.

How verify that 3 numbers in sequence are equals? [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 3 years ago.
I have to check if a sequence of any numbers are equals. The user will submit a sequence, and if, the numbers repeat in sequence, he won some points.
And the sequence to win the points it's a sequence of three. For example:
1 3 4 4 4 5
He won the points because he inputted a sequence of 3 numbers 4.
The sequence of numbers it's on a Vector. The size of the vector, It's given by the user too.
for (int i = 0; i < M.length; i++) {
if (M[i] == M[i + 1] && M[i + 1] == M[i+2]) {
if (L[i] == L[i + 1] && L[i + 1] == L[i + 2]) {
ValuePoint = 0;
} else {
PExtraM = i;
ValuePoint = 30;
}
Scanner sc1 = new Scanner(System.in);
R = sc1.nextInt();
int M[] = new int[R];
int L[] = new int[R];
for (int i = 0; i < M.length; i++) {
M[i] = sc1.nextInt();
}
for (int i = 0; i < L.length; i++) {
L[i] = sc1.nextInt();
}
//The problem It's here ************************************
for (int i = 0; i < M.length; i++) {
if (M[i] == M[i + 1] && M[i + 1] == M[i+2]) {
if (L[i] == L[i + 1] && L[i + 1] == L[i + 2]) {
ValuePoint = 0;
} else {
PExtraM = i;
ValuePoint = 30;
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at maratona.Maratona2.main(Maratona2.java:37)
Java Result: 1
i < M.length
Now let's assume the length of the Vector you are saying is 5 ok?
Now my loop will run till i is less than 5, right?
Now go to your next code :
if (M[i] == M[i + 1] && M[i + 1] == M[i+2])
Let's take the value of i as
4 (suppose)
which is in fact less than 5 and the loop condition satisfies.
But see the next code, it becomes
M[4]==M[5]&& ==M[6]
Obviously since the length of the given Vector is 5, my last element's index will be 4.
So after that **5 & 6 ** will show null only.
That's why it's saying ArrayIndexOutOfBounds Exception error at 5.
Hope this helps!
your loop variable i must stop at m.length-3
(i <m. length-2)
to have i+1=m.length-2 and i+2=m.length-1
but in your case you are trying to access i+1=m.length and i+2= m.length+1 both are out of bounds on the last two iterations
As the others already said, u r overshooting the boundaries of your array. You need to stop the loop 2 earlier to prevent.
You possably want to use something like that:
int sequenceLength = 3;
for (int i = 0; i <= M.length - sequenceLength; i++) {
boolean correct = true;
for (int j = 0; j < sequenceLength && (correct = (M[i] == M[j+i])); j++);
if (correct){
ValuePoint = 0;
} else {
PExtraM = i;
ValuePoint = 30;
break;
}
}

Counting Connections in a m*n matrix

I am trying to find the expected output to the below program..But I am getting the error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at programbasics.CountingConnections.count(CountingConnections.java:7)
at programbasics.CountingConnections.main(CountingConnections.java:26)
My question is about a matrix m*n. The elements in matrix are populated with values 1 and 0.
1 indicates in establishing connection and 0 indicates Not establishing connection.
we need to connect the available adjacent positions vertically, horizontally and diagonally and count the number of distinct connections established
My piece of code is
package programbasics;
class CountingConnections
{
static int count(int a[][], int i, int j) {
int rows = a.length;
int cols = a[0].length;
if(a[i][j] == 0) return 0;
if (i == rows - 1 && j == cols - 1)
return a[i][j];
else if (i == rows - 1)
return a[i][j + 1];
else if (j == cols - 1)
return a[i + 1][j];
else if (a[i][j] == 1)
return count(a, i + 1, j) + count(a, i, j + 1);
else
return 0;
}
public static void main(String[]args)
{
int a[][] = {{1,0,0,1},
{0,1,1,1},
{1,0,0,1}};
int i = 3;
int j = 4;
System.out.println(count(a, i, j));;
}
}
The expected output is 8. Like the positions are connected as follows
1)(0,0) -> (1,1)
2)(2,0) -> (1,1)
.
.
.
.
8) (0,3) -> (1,3)
It fails to get the expected output 8.
public static int count(int[][] a) {
int[][] paths = new int[a.length][a[0].length];
if ((paths[0][0] = a[0][0]) == 0) {
return 0;
}
for (int c = 1; c < a[0].length; c++) {
paths[0][c] = a[0][c] * paths[0][c - 1];
}
for (int r = 1; r < a.length; r++)
{
paths[r][0] = a[r][0] * paths[r - 1][0];
for (int c = 1; c < a[r].length; c++)
{
paths[r][c] = a[r][c] * (paths[r - 1][c] + paths[r][c - 1]);
}
}
return paths[a.length - 1][a[0].length - 1];
}
public static int count(int[][] a, int m, int n) {
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (a[i][j] == 1) {
if (i - 1 >= 0 && j - 1 >= 0 && a[i - 1][j - 1] == 1) {
count = count + 1;
}
if (i - 1 >= 0 && a[i - 1][j] == 1) {
count = count + 1;
}
if (i - 1 >= 0 && j + 1 < n && a[i - 1][j + 1] == 1) {
count = count + 1;
}
if (j + 1 < n && a[i][j + 1] == 1) {
count = count + 1;
}
}
}
}
return count;
}
You call if(a[i][j] == 0) in your code where you pass 3 as i and 4 as j. However Array's are zero indexed, so when you try to call a[3][4] you are trying to call
0 1 2 3 4
0 {1, 0, 0, 1}
1 {0, 1, 1, 1}
2 {1, 0, 0, 1}
3 X
4
The index where the X is. Clearly this is not a valid index in your Array.
Also your method at different points calls a[i + 1][j] and a[i][j + 1] which means that you will have to take this in account when making sure the code stays in bounds.
As to your actual method your logic seems a bit off. if(a[i][j] == 0) return 0; will return 0 and stop the recursion and return 0 without checking to see if there are any more connections. Your logic should be something more like this:
Start at 0,1.
If the index is a 1
Look one index to the right, one down and to the right (The diagonal) down one, and down one and to the left (The second diagonal).
If any of the numbers at those index's are 1's then up the counter.
Continue to iterate through the matrix, but keep in mind that you are checking one row down and over, so you will only loop until less than length -1 for for both the row and column. Also make sure that you are starting at index a[i][1] as you will be needing to check a[a+1][j-1] and if j == 0 you will be trying to call a[a+1][-1] which will cause another index out of bounds
private int countConnections(int[][] a, int rows, int columns) {
//cartesian plane coordinates around a point
final int[] x = {1, 1, 1, -1, -1, -1, 0, 0};
final int[] y = {1, -1, 0, 1, -1, 0, 1, -1};
int count = 0;
boolean[][] visited = new boolean[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
for (int k = 0; k < 8; k++) {
int l = i + x[k];
int m = j + y[k];
//check for connections only if the given cell has value 1
if (a[i][j] == 1 && canVisit(l, m, rows, columns, visited) && a[l][m] == 1) {
count++;
}
}
visited[i][j] = true;
}
}
return count;
}
private boolean canVisit(int i, int j, int rows, int columns, boolean [][] visited) {
return i < rows && j < columns && i >= 0 && j >= 0 && !visited[i][j];
}
Check all the 8 cells around a cell whose cell value is 1 and when traversed mark it as visited.

Drawing a diamond of numbers in a 2d array Java

I've been solving some coding questions to get myself prepared for a coding interview, and found out a question that seemed kind of puzzling. I solved the question after spending some time on it; however, the code looks hardcoded and has no style. So, I was wondering if I could get some feedbacks on styling the code, or perhaps getting an better idea of approaching the problem.
The question basically asks you to draw a diamond of numbers with a pattern in 2d array.
It gives a coordinate of 'x' and range of x. From the x, the numbers spread one by one until the range. So, there are 4 different inputs, N (the size of an array), X, Y (the coordinate of 'x' as (rows, cols)), and R (range).
If they were given a size of 8, coordinate of (4,5) with a range of 3, the result would be like,
0 0 0 0 3 0 0 0
0 0 0 3 2 3 0 0
0 0 3 2 1 2 3 0
0 3 2 1 x 1 2 3
0 0 3 2 1 2 3 0
0 0 0 3 2 3 0 0
0 0 0 0 3 0 0 0
0 0 0 0 0 0 0 0
And the below is what I have,
int n = sc.nextInt();
char[][] arr = new char[n][n];
int r = sc.nextInt() - 1;
int c = sc.nextInt() - 1;
int range = sc.nextInt();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
arr[i][j] = '0';
}
}
arr[r][c] = 'x';
int num = 1;
for (int i = 0; i < range; i++) {
//Cross
if (c-num > -1) {
arr[r][c - num] = (char) (num + '0');
}
if (c+num < n) {
arr[r][c + num] = (char) (num + '0');
}
if (r-num > -1) {
arr[r - num][c] = (char) (num + '0');
}
if (r+num < n) {
arr[r + num][c] = (char) (num + '0');
}
//Diagonal
if (i > 0) {
int sum = num - 1, delta = 1;
while (sum != 0) {
if (r-sum > -1 && c+delta < n) {
arr[r - sum][c + delta] = (char) (num + '0');
}
sum--;
delta++;
}
sum = num - 1; delta = 1;
while (sum != 0) {
if (r+sum < n && c-delta > -1) {
arr[r + sum][c - delta] = (char) (num + '0');
}
sum--;
delta++;
}
sum = num - 1; delta = 1;
while (sum != 0) {
if (r-sum > -1 && c-delta > -1) {
arr[r - sum][c - delta] = (char) (num + '0');
}
sum--;
delta++;
}
sum = num - 1; delta = 1;
while (sum != 0) {
if (r+sum < n && c+delta > -1) {
arr[r + sum][c + delta] = (char) (num + '0');
}
sum--;
delta++;
}
}
num++;
}
I could not figure out any other way to take care of the diagonal numbers other than using four different while-loops. I would appreciate any kind of feedback. Thanks in advance!
You can just loop over the array once, and set the values based on the relative distance of the current location (i, j) to the fixed coordinate (x, j).
Your code could look like this:
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
// variables
int n = 8;
int x = 4 - 1; // coordinates are one-based
int y = 5 - 1; // coordinates are one-based
int r = 3;
char[][] array = new char[n][n];
// logic
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int dist = Math.abs(x - i) + Math.abs(y - j); // calculate distance
if(dist == 0) { // at x,y
array[i][j] = 'x';
} else if (dist <= r) { // distance to x,y is within range
array[i][j] = (char) (dist + '0');
} else { // distance to x,y is outside of range
array[i][j] = '0';
}
}
}
// dump output
System.out.println(Arrays.deepToString(array)
.replace("], ", "]\n")
.replace("[", "")
.replace("]", "")
.replace(", ", " "));
}
}
Which yields the following output:
0 0 0 0 3 0 0 0
0 0 0 3 2 3 0 0
0 0 3 2 1 2 3 0
0 3 2 1 x 1 2 3
0 0 3 2 1 2 3 0
0 0 0 3 2 3 0 0
0 0 0 0 3 0 0 0
0 0 0 0 0 0 0 0
If you want to be even more concise, you can replace the branched if… else if… else statement with ternary operators:
array[i][j] = dist == 0 ? 'x' : dist <= r ? (char) (dist + '0') : '0';
Here's a fairly compact method. On each iteration i we fill a single-character wide i+1 by i+1 diamond-shaped ring, centered on (row, col), with value i. To avoid filling the interior of the diamond we check that the manhattan distance to (row, col) is equal to i - this is only true for cells on the boundary of the diamond.
static char[][] buildDiamond(int n, int row, int col, int range)
{
char[][] arr = new char[n][n];
for(char[] a : arr) Arrays.fill(a, '0');
arr[row][col] = 'x';
for(int i=1; i<=range; i++)
for(int j=0; j<=i; j++)
for(int k=0; k<=i; k++)
if(Math.abs(k-j) + Math.abs(k+j-i) == i)
arr[row+k-j][col+k+j-i] += i;
return arr;
}
Test:
public static void main(String[] args)
{
for(char[] a : buildDiamond(7, 3, 3, 3))
System.out.println(new String(a).replaceAll(".", "$0 "));
}
Output:
0 0 0 3 0 0 0
0 0 3 2 3 0 0
0 3 2 1 2 3 0
3 2 1 x 1 2 3
0 3 2 1 2 3 0
0 0 3 2 3 0 0
0 0 0 3 0 0 0
You can try using floodfill, although depending on your level it might be a bit far.
https://en.wikipedia.org/wiki/Flood_fill
EDIT: Robby Cornelissen's code looks much cleaner and simpler than mine so you should probably check out his. However, floodfill is a pretty important concept for later on so might as well check it out.
The article is pretty long, but the GIF in the article is the most important part.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class test {
public static void main(String[] args) throws IOException {
//Get inputs (I used BufferedReader, Scanner works fine as well)
//My inputs are formatted as 'N X Y R' (ex. '8 4 5 3')
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int N = Integer.parseInt(st.nextToken());
int R = Integer.parseInt(st.nextToken()) - 1;
int C = Integer.parseInt(st.nextToken()) - 1;
int range = Integer.parseInt(st.nextToken());
char[][] arr = new char[N][N];
//Make everything in array '0'
for (int i = 0; i < N; i++) {
Arrays.fill(arr[i], '0');
}
//Floodfill using BFS
//FYI: this BFS is iterative, not recursive
Queue<int[]> q = new LinkedList<>();
q.add(new int[]{0, R, C});
while (!q.isEmpty()) {
int[] current = q.remove();
if (arr[current[1]][current[2]] == '0' && current[0] <= range) {
arr[current[1]][current[2]] = (current[0]+"").charAt(0);
if(current[1]+1 < N) q.add(new int[]{current[0]+1, current[1]+1, current[2]});
if(current[1]-1>= 0) q.add(new int[]{current[0]+1, current[1]-1, current[2]});
if(current[2]+1 < N) q.add(new int[]{current[0]+1, current[1], current[2]+1});
if(current[2]-1>= 0) q.add(new int[]{current[0]+1, current[1], current[2]-1});
}
}
arr[R][C] = 'x';
//Print out the final grid
for (int i = 0; i < N; i++) {
for (int j = 0; j< N; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}

Adding numbers in an array

In this case, I want to add two numbers in this array in to obtain a specific sum when added, let’s say, 4. I also want to output what indices are being added in order to obtain that specific sum, just to see the inner workings of my code. What am I doing wrong?
public static int addingNumbers(int[] a) {
int i1 = 0, i2 = 0;
for(int i = 0, j = i + 1; i < a.length && j < a.length; i++, j++) {
if(a[i] + a[j] == 4) { // index 0 and index 2 when added gives you a sum 4
i1 = i;
i2 = j;
}
}
System.out.println("The indices are " + i1 + " and " + i2);
return i1;
}
public static void main(String args[]) {
int[] a = {1, 2, 3, 4, 5, 6};
System.out.println(addingNumbers(a));
}
The error you are making is using only one loop that iterates over the array once:
for(int i = 0, j = i + 1; i < a.length && j < a.length; i++, j++) {
In your loop you are setting i to 0 and j to 1, then you increment them with every step. So you are only comparing adjacent places in your array:
iteration: a[0] + a[1]
iteration: a[1] + a[2]
iteration: a[2] + a[3]
etc. pp
Since your array doesn't have two adjacent elements that sum up to 4 your if(a[i] + a[j] == 4) will never be entered and i1, i2 will still be 0 when the loop is finished.
To compare every array element with each other you should use 2 nested loops:
public static int addingNumbers(int[] a) {
int i1 = -1, i2 = -1;
for(int i = 0; i < a.length ; i++) {
for(int j = i+1; j < a.length ; j++) {
if(a[i] + a[j] == 4) { // index 0 and index 2 when added gives you a sum 4
i1 = i;
i2 = j;
}
}
}
if(i1>=0 && i2 >=0) {
System.out.println("The indices are " + i1 + " and " + i2);
}
return i1;
}
Note that this will only print out the last detected 2 indices that add up to 4. If you want to be able to detect multiple possible solutions and print them out could for example move the System.out.println into the if block.
It can never be == 4 because 1+2=3 then 2+3=5. So it does nothing.
There is a logic error in your code. The sum you are checking in your code is never for.
I added some debug output for easy checking:
public static int addingNumbers(int[] a) {
int i1 = 0, i2 = 0;
for(int i = 0, j = i + 1; i < a.length && j < a.length; i++, j++) {
int sum = a[i] + a[j];
System.out.println(sum);
if(sum == 4) { // index 0 and index 2 when added gives you a sum 4
i1 = i;
i2 = j;
}
}
System.out.println("The indices are " + i1 + " and " + i2);
return i1;
}
Output is: 3
5
7
9
11
The indices are 0 and 0
0
this algorithm will never be able to add a[0] to a[2], be cause when you put j=i+1 it will always be 0+1 then 1+2 ... The sum of tow adjacent numbers is never pair.
An other matter is the condition to stop your loop must be j < a.length-1
try to explain more of what you want from your algorithm.
Are you over complicating this on purpose?
Trying to figure out your intention for this task.
Why don't you just do (this is pseudo):
for length of i {
if (a[i] + a[i+1] == 4) {
System.out.println("The indices are " + a[i] + " and " + a[i+1]);
}
}

Categories

Resources