Magic Square gives ArrayIndexOutOfBoundException - java

I have been working on Magic Square formation, after reading through the algo, I found out there are certain set of rules to be followed while forming the MagicSquare.
The algo which I'm following is :
The magic constant will always be equal to n(n^2 + 1)/2, where n is the dimension given.
Numbers which magicSquare consists will always be equals 1 to n*n.
For the first element that is 1, will always be in the position (n/2, n-1).
Other elements will be placed like (i--,j++)
The condition to be put through for placing an elements are :
a) If i < 0, then i = n-1.
b) If j == n, then j = 0.
c) This is a special case, if i < 0 and j=n happens at the same time, then i = 0, j = n-2.
d) If the position is already occupied by some other element, then i++, j = j-2.
Then input the element inside the magicSquare based upon the conditions.
Based upon the above algo, I have written down a code, and due to some reason I'm getting
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at Main.generateMagicSquare(Main.java:25)
at Main.main(Main.java:58)
This is weird. I have checked, and feels like it is safe to use the code to get the desired result, but I don't know where I'm going wrong.
Code
static void generateMagicSquare(int n){
int[][] magicSquare = new int[n][n];
//initialising for pos of the elem 1
int i = n/2, j = n-1;
magicSquare[i][j] = 1;
//the element consist by the magic square will always be equal to 1 to n*n
for(int num=2; num <= n*n; num++){
//it must go like this, for any other element
i--; j++;
// if the element is already present
if(magicSquare[i][j] != 0){
i++;
j -= 2;
}else{
if(i < 0)
i = n-1;
if(j == n)
j = 0;
if(i < 0 && j == n){
i = 0;
j = n-2;
}
}
magicSquare[i][j] = num;
}
for(int k=0; k<n; k++){
for(int l=0; l<n; l++){
System.out.print(magicSquare[k][l] + " ");
}
System.out.println();
}
}
Any help would be appreciated. Thanks. Since I could have copied and pasted the code from internet, but I want to learn it in my way, and your help would help me achieve what I want. :)
EDITS
After reading through the exception, I made some amendments in my code, but still some of the result didn't come upto the mark.
Here is my updated code =======>
static void generateMagicSquare(int n){
int[][] magicSquare = new int[n][n];
//initialising for pos of the elem 1
int i = n/2, j = n-1;
magicSquare[i][j] = 1;
//the element consist by the magic square will always be equal to 1 to n*n
for(int num=2; num <= n*n; num++){
//it must go like this, for any other element
i--; j++;
if(i < 0){
i = n-1;
}
if(j == n){
j = 0;
}
if(i < 0 && j == n){
i = 0;
j = n-2;
}
if(magicSquare[i][j] != 0){
i++;
j -= 2;
}else{
magicSquare[i][j] = num;
}
}
for(int k=0; k<n; k++){
for(int l=0; l<n; l++){
System.out.print(magicSquare[k][l] + " ");
}
System.out.println();
}
}
I get this output :
2 0 6
9 5 1
7 3 0
Still not the right answer to follow.

This line throws the error:
if(magicSquare[i][j] != 0)
and the problem is that the array magicSquare is initialized as:
int[][] magicSquare = new int[n][n];
meaning that it has n columns with indexes from 0 to n - 1 (indexes are zero based).
The variable j is initialized as
j = n-1;
and later this line:
j++;
makes j equal to n
so when you access magicSquare[i][j] you are trying to access magicSquare[i][n] which does not exist.

The index of an array is an integer value that has value in interval [0, n-1], where n is the size of the array. If a request for a negative or an index greater than or equal to size of array is made, then the JAVA throws a ArrayIndexOutOfBounds Exception. You have to check the value of i and j before using it in array. You can use the below code :
for(int num=2; num <= n*n; num++){
i--; j++;
//Here We have to check the value of i and j i.e. it should less than or equal to the length of array.
if((i <= magicSquare[0].length-1 && j <= magicSquare[0].length-1))
{
if(magicSquare[i][j] != 0){
i++;
j -= 2;
}else{
if(i < 0)
i = n-1;
if(j == n)
j = 0;
if(i < 0 && j == n){
i = 0;
j = n-2;
}
}
magicSquare[i][j] = num;
}
}
For understanding ArrayIndexOutOfBoundsException, Please visit :
https://www.geeksforgeeks.org/understanding-array-indexoutofbounds-exception-in-java/

Related

Pascal's triangle in Java [duplicate]

This question already has answers here:
Pascal's triangle positioning
(5 answers)
Closed 1 year ago.
Java beginner here! As part of practicing programming, I've run into Pascal's triangle. I tried to implement a solution where the triangle is printed like so:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
So roughly right-sided. My solution though runs into multiple errors, and although I would appreciate help with that, I would primarily like to know if I am thinking correctly with my solution. (For some functions I am using a custom library)
public static void main(String[] args) {
int input = readInt("Enter triangle size, n = ");
array = new int[input][input];
for (int i = 0; i < input; i++) { // rows
for (int j = 0; j < i + 1; j++) { // columns
if (i = 0) {
array[i][0] = 1;
} else if (i != 0 && i == j) {
array[i][j] = 1;
} else {
array[i][j] = array[i - 1][j] + array[i - 1][j - 1];
}
}
}
// print out only the lower triangle of the matrix
for (int i = 0; i < input; i++) {
for (int j = 0; j < input; j++) {
if (i <= j) {
System.out.println("%d ", array[i][j]);
}
}
}
}
You were on the right track. Here's how I implemented it:
Scanner sc = new Scanner(System.in);
System.out.print("Enter triangle size, n = ");
int n = sc.nextInt();
sc.close();
//This will be a jagged array
int[][] array = new int[n][0];
for (int i = 0; i < n; i++) {
//Add the next level (it's empty at the start)
array[i] = new int[i + 1];
for (int j = 0; j <= i; j++) {
//At the ends, it's just 1
if (j == 0 || j == i) {
array[i][j] = 1;
} else { //The middle
array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
}
}
}
for (int i = 0; i < n; i ++) {
for (int j = 0; j <= i; j++) {
//printf is what you use to do formatting
System.out.printf("%d ", array[i][j]);
}
//Without this, everything's on the same line
System.out.println();
}
Your else part was correct, but you didn't check if j equaled 0 before that. Instead of setting the current element to 1 when i was 0 or when i equaled j, you should have done it when j was 0 or when i equaled j. Because of this mistake, in later rows where i was not 0, but j was, you tried to access array[i - 1][j - 1], which was basically array[i - 1][-1], causing an IndexOutOfBoundsException.
I also made a jagged array instead of an even matrix because it made more sense that way, but it shouldn't matter much.
Also, this wasn't an error, but you did else if (i!=0 && i==j) The i != 0 part is unnecessary because you checked previously if i == 0.
Link to repl.it

Why does the inner loop range make a difference in the way this problem is solved?

Write a static method printNumbers that takes an integer max as an argument and prints out all perfect numbers that are less than or equal to max.
At first, I kept getting the wrong answer because the inner loop was set to j < max before I changed it to j < i. However, I don't understand why that range would matter, because wouldn't i % j != 0 anyway, even if the range of j were to be larger?
for (int i = 1; i <= max; i++) {
int sum = 0;
for (int j = 1; j < i; j++) {
if (i % j == 0) {
sum += j;
}
}
if (sum == i) {
System.out.print(sum + " ");
}
}
If I changed the inner loop j < max, then printNumbers(6) gives both 1 and 6, but printNumbers(500) gives only 1 and no other number.
If you set j < max in the inner loop, then when j = i, i % j == 0 returns true and skews your result.
This is a good example of a mathematical error to watch out for in coding.

Checking for out of bounds in a 2D array

I'm trying to check the neighboring values of each element in a 2D array but am getting an IndexOutOfBoundsException when I reach the sides of the array or a corner. For example if my array is:
|2|4|2|7|8|
|8|1|0|5|6|
|0|3|1|5|2|
|1|9|7|2|0|
I know that all the neighbors of 8 are 7,5 and 6, but my if statements don't check the bounds properly. The code I have for this is:
int numOfRows = imageArray.length;
int numOfColumns = imageArray[0].length;
for(int i = 0; i < numOfRows; i++)
for(int j = 0; j < numOfColumns; j++)
if((j+1) < numOfColumns-1)
if((i+1) < numOfRows-1)
if((j-1) > 0 )
if((i-1) > 0 )
if((i+1) < numOfColumns-1 && (j+1) < numOfRows-1)
if((i-1) >= 0 && (j-1) >= 0)
if((i+1) < numOfColumns-1 && (j-1) >= 0)
if((i-1) >= 0 && (j+1) < numOfRows-1)
I've been working on this for a while and have gone through many different techniques to solve this. Any help would be great. Thanks.
If you're trying to get all the neighbor cells and do something with them, for example add them, then you need to do some sort of bounds checking, for example something modified from this could work:
for (int i = 0; i < numOfRows; i++) {
for (int j = 0; j < numOfCols; j++) {
// check all bounds out of range:
int iMin = Math.max(0, i - 1);
int iMax = Math.min(numOfRows - 1, i + 1);
int jMin = Math.max(0, j - 1);
int jMax = Math.min(numOfCols - 1, j + 1);
// loop through the above numbers safely
for (int innerI = iMin; innerI <= iMax; innerI++) {
for (int innerJ = jMin; innerJ <= jMax; innerJ++) {
if (i != innerI && j != innerJ) {
// do what needs to be done
}
}
}
}
}
Caveat: code has not been compiled nor tested and is mainly to show you the idea of what can be done rather than a copy-paste solution

counting negative numbers in array

I am trying to find the counts for negative numbers in a 2d-array ( square- matix). In matrix if you go from up to down and left to write number increases. Logic here is to start from last column and proceed to the left. If you find the neg num then increase the row index and proceed the same way till the last row. I am getting the error in java code but not in python.
public class O_n
{
public static void main(String[] args)
{
int firstarray[][] = {{-2,-1,0},{-1,0,1},{0,1,2}};
int secondarray[][] = {{-4,-3,-2},{-3,-2,-1},{-2,-1,0}};
System.out.print ("First array has"+count_neg(firstarray));
System.out.println("negative numbers");
System.out.print ("Second array has"+count_neg(secondarray));
System.out.println("negative numbers");
}
public static int count_neg(int x[][]){
int count = 0;
int i = 0; //rows
int j = x.length - 1; //columns
System.out.println("max column index is: "+j);
while ( i >=0 && j<x.length){
if (x[i][j] < 0){ // negative number
count += (j + 1);// since j is an index...so j + 1
i += 1;
}
else { // positive number
j -= 1;
}
}
return (count);
}
}
I am getting this output
max column index is: 2
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at O_n.count_neg(O_n.java:22)
at O_n.main(O_n.java:9)
/home/eos/.cache/netbeans/8.1/executor-snippets/run.xml:53: Java
returned: 1
BUILD FAILED (total time: 0 seconds)
What is wrong with this code? the same thing worked in python...
def count_neg(array):
count = 0
i = 0 # row
j = len(array) -1 # col
# since we are starting from right side
while j >= 0 and i < len(array):
if array[i][j] < 0:
count += (j + 1)
i += 1
else:
j -= 1
return count
print(count_neg([[-4,-3,-1,1],[-2,-2,1,2],[-1,1,2,3],[1,2,4,5]]))
I would write the method like this, just go through the 2d array and increase count each time a negative number is found
public static int count_neg(int x[][]){
int count = 0;
for(int i = 0; i < x.length; i++){
for(int j = 0; j < x[i].length; j++){
if(x[i][j] < 0){
count++;
}
}
}
return (count);
}
Your indexes are reversed from the python version:
while j >= 0 and i < len(array)
To the Java version:
while (i >= 0 && j < x.length)
// Change to
while (j >= 0 && i < x.length)
Output:
max column index is: 2
3
If you are using Java8, you can use streams to implement count_neg:
public static int countNeg(int x[][]) {
long count = Stream.of(x)
.flatMapToInt(arr -> IntStream.of(arr))
.filter(i -> i < 0)
.count();
return Math.toIntExact(count);
}
First of all your algorithm don't find the count of negative numbers.
Here are the results of the python code:
print(count_neg([[1, 1, -1],[1, 1, -1],[1, 1, -1]])) result - 9
print(count_neg([[1, 1, -1],[1, 1, 1],[1, 1, 1]])) result - 3
So the provided code finds sum of column indexes + 1 for some negative numbers, not all. And for your test arrays it's return pseudo correct counts.
To find the count of negative numbers in a two-dimentional array you just have to get each number, check if the one is less than zero and increase the counter by one if it's true. So it's impossible to get the correct result with complexity better than O(n2).
Here the correct code in Java of doing that:
public static int count_neg(int x[][]){
int count = 0;
for(int i = 0; i < x.length; i++){
for(int j = 0; j < x[i].length; j++){
if(x[i][j] < 0) count++;
}
}
return count;
}
Here a small change in the algorithms to produce correct result with columns which don't contain negative numbers:
while j >= 0 and i < len(array):
if array[i][j] < 0:
count += (j + 1)
i += 1
else:
j -= 1
if j < 0:
i += 1
j = len(array) - 1
You can test it with the following array [[1,2,4,5],[-2,-2,1,2],[-1,1,2,3],[1,2,4,5]]

Printing rows of increasing amounts of even numbers

I'm trying to print the following:
2
2 4
2 4 6 ..etc
The code I have written (below) prints the following:
2
4 6
8 10 12 ...etc
Can anyone spot where I'm going wrong? The n variable comes from the main method which I am not including.
public static void printEvenTable(int n) {
int i;
int j;
int k = 0;
for (i = 1; i <= n; i++) {
for (j = 0; j < i; j++)
System.out.print(" " + (k += 2));
System.out.println(" ");
}
}
You need to prevent the variable k from using its old value by reassigning 0 to it right after the second for loop. Placing k = 0; before the second for loop makes redundant reassigning because it has already been assigned right before the loop. Ensure program optimization. If you are using a good editor, it show you some warning if placed before the second for loop.
for (i = 1; i <= n; i++) {
for (j = 0; j < i; j++) {
System.out.print(" " + (k += 2));
}
k=0;
System.out.println(" ");
}
Here, the inner loop is increasing the variable k by 2 in each steps after the first execution of the inner loop k becomes 2 from the initial value 0. In the second iteration of the outer loop k starts as 2. After k+=2, k becomes 4 so second line of output starts from 4. That's why we need to re-initialize k to 0 before each inner loop.
public static void printEvenTable(int n) {
int i;
int j;
int k = 0;
for (i = 1; i <= n; i++) {
k = 0;
for (j = 0; j < i; j++)
System.out.print(" " + (k += 2));
System.out.println(" ");
}
}

Categories

Resources