ArrayIndexOutOfBoundsException error on two-dimensional array [duplicate] - java

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 5 years ago.
I want to check the 8th positions adjacent to each of the positions of my two-dimensional array but the firsts ones give me error because there aren't positions there.
How can I avoid that error? The same happened to me in the past and I couldn't solve it neither.
Example image of what I want to do:
Code of my method:
private static void evoluciona(char[][] tauler2, char[][] tauler22) {
for(int i = 0; i < files; i++) {
for(int j = 0; j < columnes; j++) {
tauler2[i][j] = tauler[i][j];
}
}
for(int i = 0; i < files; i++) {
for(int j = 0; j < columnes; j++) {
if(tauler2[i][j] == 'x') {
int cont = 0;
if(tauler2[i-1][j] == '*') {
cont++;
}
if(tauler2[i-1][j-1] == '*') {
cont++;
}
if(tauler2[i-1][j+1] == '*') {
cont++;
}
if(tauler2[i][j-1] == '*') {
cont++;
}
if(tauler2[i+1][j-1] == '*') {
cont++;
}
if(tauler2[i+1][j] == '*') {
cont++;
}
if(tauler2[i+1][j+1] == '*') {
cont++;
}
if(tauler2[i][j+1] == '*') {
cont++;
}
if(cont == 2 || cont == 3) {
tauler2[i][j] = '*';
}
}
else if(tauler2[i][j] == '*') {
int cont = 0;
if(tauler2[i-1][j] == '*') {
cont++;
}
if(tauler2[i-1][j-1] == '*') {
cont++;
}
if(tauler2[i-1][j+1] == '*') {
cont++;
}
if(tauler2[i][j-1] == '*') {
cont++;
}
if(tauler2[i+1][j-1] == '*') {
cont++;
}
if(tauler2[i+1][j] == '*') {
cont++;
}
if(tauler2[i+1][j+1] == '*') {
cont++;
}
if(tauler2[i][j+1] == '*') {
cont++;
}
if(cont == 2 || cont == 3) {
tauler2[i][j] = '*';
}
else {
tauler2[i][j] = 'x';
}
}
}
}
}

I had a similar problem when programming my own little Minesweeper clone around christmas.
I ended up with a field class that knows its neighbors.
class Field {
char value;
Field[] neighbors;
}
Whenever initializing a new board those 'connections' were sort of precompiled.
class FieldManager {
void initializeFields(int firstDimension, int secondDimension) {
fields = new Field[firstDimension][secondDimension];
for(int i = 0; i < fields.length; i++) {
for(int j = 0; j < fields[i].length; j++) {
fields[i][j] = new Field();
fields[i][j].neighbors = neighborsFor(i, j);
}
}
}
private Field[] neighborsFor(int iIn, int jIn) {
List<Field> result = new ArrayList<>();
for(int i = iIn - 1; i <= iIn + 1; i++) {
for(int j = jIn - 1; j < jIn + 1; j++)
// do some range checks and fill result
}
}
return result.toArray(new Field[result.size()]);
}
Field[][] fields;
}
Instead of array you can as well use Collections, such as ArrayList. Especially the newer java versions have a lot of useful utility built around those interfaces.

I'd recommend explicitly checking against boundaries!
Modify your if statements, so that whenever you have i+1, j+1 you check it's not too large ( i < files and j < columnes), and i-1, j-1 that they are not 0 ( i > 0 and j > 0).
As you are counting neighboring stars, this method will not add extra stars if you are on the border.
Alternatively, the "lazy way", you can try{} catch(ArrayOutOfBoundsException e) { continue; } inside the inner loops!

In all the places that you have an index of i-1 or j-1, on the first iteration of either cycle (i or j) you can have an index of -1 as per your exception in the stack trace, which causes the ArrayIndexOutOfBoundsException.
Instead of catching it and ignoring it, place an if around the areas that can cause this exception before doing anything.
// your code
...
if (i - 1 >= 0) {
if(tauler2[i-1][j] == '*') {
cont++;
}
}
...
and likewise in the case of tauler2[i][j-1], a condition check on j - 1 >= 0.

you are accessing such an index that is not in array. As you are starting forloops i-e i=0 and j=0, and in if conditions u r using indexes that are [i-1] and [j-1]. here u r getting exception of index out of bounds. eliminate or change these conditions.

Related

Printing only NON-BOUNDARY and CORNER elements of an (n*n) array

I am to write a program that prints ONLY the NON-BOUNDARY AND CORNER elements of an (n*n) array, for my assignment, and this is the main part of the code:
The output I am getting is this:
As you can see, the non-boundary elements (6,7,10,11) are not in their correct positions, which I believe, is because of incorrect printing of tab spaces within the loop. (My code is totally a mess) I would like some help or suggestions to fix this. Thanks!
I generally find that flattening things (the if-conditions in particular), and putting conditions into boolean-returning methods helps. Try something like
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++ {
if (isCorner(i,j,n) || !isEdge(i,j,n)) {
//...
} else {
//...
}
}
System.out.println();
}
where isCorner(i,j,n) and isEdge(i,j,n) are defined something like
public boolean isCorner(int row, int column, int gridSize) {
//...
}
A you got a solution, just missing spaces, I'll add some smart things:
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
boolean visible = (i % (n - 1) == 0) == (j % (n - 1) == 0);
if (visible) {
System.out.printf(" %4d", a[i][j]);
} else {
System.out.print(" ");
}
}
System.out.println();
}
No longer any problems with tabs "\t", though I used spaces here.
Keep it simple, too many cases just cause problems - as you experienced.
The trick here is to consider whether to print or not. Hence I started with
a variable visible.
The border condition
i == 0 || i == n - 1
could also be written with modulo as
i % (n - 1) == 0
If this is "too smart", hard to grasp reading:
boolean iOnBorder = i % (n - 1) == 0;
boolean jOnBorder = j % (n - 1) == 0;
boolean visible = iOnBorder == jOnBorder;
The "X" pattern checks the _equivalence of i-on-border and j-on-border.
For the rest: formatted printf allows padding of a number.
Try this i have optimized your if condition
No need to again check for i == 0 or i == n-1
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==0 || i==n-1){
if(j==0 || j==n-1){
System.out.print(a[i][j]);
}
}else{
if(j != 0 && j!= n-1){
System.out.print(a[i][j]);
}
}
System.out.print("\t");
}
System.out.println();
}
Just gave a try in case you might find it helpful.
public static void main(String[] args) throws ParseException {
int[][] ar = new int[4][4];
int[] input = new int[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int pointer=0;
int imin=0,jmin=0,imax=3,jmax=3;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
ar[i][j]=input[pointer];
pointer++;
}
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(!((i==imax && j==jmin)||(i==imin && j==jmax)||i==j) && //For skipping the corners
(i == imin || j == jmin || i == imax || j == jmax)){// Not to print the borders
continue;
}
else {
System.out.println(ar[i][j]);
}
}
}
}

Game Of Life loop error

So I'm currently working on a program based on Conway's Game of Life, and this certain method requires me to update the 2d array to define which cells are alive. I've run my JUnit tests, but when the test for the method runs, it says it's infinitely looping. Any ideas why?
public void update() {
boolean temp ;
for (int i = 0; i < numberOfRows(); i++) {
for (int j = 0; j < numberOfColumns(); j++) {
temp = false;
if (cellAt(i, j)) {
temp = true;
}
if (temp=true) {
if (neighborCount(i, j) < 2 || neighborCount(i, j) > 3) {
society[i][j] = false;
}
} else {
if (neighborCount(i, j) == 3) {
society[i][j] = true;
}
}
}
}
}
Here is the other methods that are used in this one
cellAt():
public boolean cellAt(int row, int col) {
if (society[row][col] == true) {
return true;
} else {
return false;
}
}
neighborCount():
public int neighborCount(int row, int col) {
int counter = 0;
for (int i = ((row + numberOfRows() - 1) % numberOfRows()); i == ((row + 1) % numberOfRows())
|| i == row
|| i == (((row + numberOfRows() - 1)) % numberOfRows())
|| i == numberOfRows(); i++) {
i = i % numberOfRows();
for (int j = (((col + numberOfColumns() - 1)) % numberOfColumns()); j == ((col + 1) % numberOfColumns())
|| j == col
|| j == (((col + numberOfColumns() - 1)) % numberOfColumns())
|| j == numberOfColumns(); j++) {
j = j % numberOfColumns();
if (society[i][j] == true) {
counter++;
}
}
}
return counter;
}
You need to use comparison(==) instead of assignment(=) here:
if (temp=true) {
which will always return true
Change it to
if (temp == true) {
or simply use "Jean-François Savard" suggestion
if(temp)
Figured it out. neighborCount() was just horribly written and the for loops were repeating.

Solution of twoTwo riddle on codingBat in Java

The question is about Solving this problem from codingBat in Java.
Problem Statement:
Given an array of ints, return true if every 2 that appears in the array is next to another 2.
twoTwo({4, 2, 2, 3}) → true
twoTwo({2, 2, 4}) → true
twoTwo({2, 2, 4, 2}) → false
First of all going by the problem statement that every 2 that appears in the array is next to another 2. then
do you think as suggested the outcome for the first inputs shown above
should be true?
twoTwo({4, 2, 2, 3}) → true
Because as I see it it the first 2 itself that appears in the array is next to 4 not 2
am I confused or it's a wrongly stated question? I had to grapple with the problem to somehow get the right code to crack the problem as below but it seems a hotch potch:
public boolean twoTwo(int[] nums) {
if(nums.length==0)
{
return true;
}
if(nums.length==1)
{
return !(nums[0]==2);
}
if((nums.length==2))
{
if((nums[1]==2)&&(nums[0]==2))
return true;
else
return false;
}
for(int i=0;i+2<nums.length;i++)
{
if((nums[i]!=2)&&(nums[i+1]==2)&&(nums[i+2]!=2))
return false;
}
if((nums[nums.length-2]!=2)&&(nums[nums.length-1]==2))
return false;
return true;
}
Any efficient alternate solutions are welcome.
Thanks!
Here's how I would do it. It's a bit easier to follow I think:
public boolean twoTwo(int[] nums)
{
for (int i=0; i<nums.length; i++)
{
if (nums[i] != 2)
continue;
if (i >= 1 && nums[i-1] == 2)
continue;
if (i < (nums.length-1) && nums[i+1] == 2)
continue;
return false;
}
return true;
}
The solution I got to the problem is below:
public boolean twoTwo(int[] nums) {
final int length = nums.length;
for (int i = 0; i < length;){
int count = 0; // Used to count following 2's
while(i < length && nums[i++] == 2){
count++;
}
if(count == 1){ // No adjacent 2's! Set doesn't work.
return false;
}
}
return true; // Didn't come across a lone 2
}
The way that I handle this, is that I count all the adjacent 2's. If the count is not 1, we are good. This means that there was either no 2 at that index, or a group of 2's was present. This holds, since we traverse the array in a single direction.
A good thing about this solution is that it will work for an array of any size. Note that it would have a linear complexity, even though 2 loops are present. They both just traverse using the same index value, only ever sweeping over the array once.
If at any time we find a 2, then check the following only to find there are 0 following 2's (denoted by count), we return false.
public boolean twoTwo(int[] nums) {
for (int i=0; i<nums.length; i++) {
if(nums[i] == 2) { //If current number is 2
if (
// if prev or next is not 2 return true
!(i-1>=0 && nums[i-1] == 2) &&
!(i+1<nums.length && nums[i+1] == 2)
) { return false; }
}
}
return true;
}
For the sake of simplicity and clean code, this code forces the check
i-1>=0 and i+1<nums.length in every iteration.
This can be avoided by iterating from (1...nums.length-1) and checking the edge cases separately.
I know this is an old question, but I came up with a new solution. Short, and with no complicated conditionals.
public boolean twoTwo(int[] nums) {
int position = -2;
boolean result = true;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 2) {
result = position == i - 1;
position = i;
}
}
return result;
}
Next to means either before or after. Loop through each number and check the values before and after to see if there's an adjacent 2. The special cases are when you're checking the 1st and last element because there won't be an element before or after to check.
public boolean twoTwo(int[] nums) {
if(nums.length == 1 && nums[0] == 2)
return false;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 2) {
if(i == 0) { // check the next element
if(nums[i+1] != 2)
return false;
}
else if(i == (nums.length - 1)) { // check the previous element
if(nums[i-1] != 2)
return false;
}
else { // check both
if(nums[i+1] != 2 && nums[i-1] != 2)
return false;
}
}
}
return true;
}
Here is mine solution to two two's problem. I think my solution is clear i.e. understandable.
package codingbat.array2;
public class TwoTwo
{
public static void main(String[] args)
{
}
public boolean twoTwo(int[] nums)
{
boolean twoTwo = true;
for (int i = 0; i < nums.length; i++)
{
if (2 == nums[i])
{
if (i > 0 && 2 == nums[i - 1]
|| nums.length > i+1 && 2 == nums[i+1])
{
twoTwo = true;
i++;
}
else
{
twoTwo = false;
break;
}
}
}
return twoTwo;
}
}
public boolean twoTwo(int[] nums) {
for(int i = 0 ; i < nums.length; i++ ) {
int count = 0;
if(nums[i] == 2 ) {
while(i+1 < nums.length && nums[i+1] == 2 ) {
count ++;
i++;
}
if (count == 0 ) {
return false;
}
}
}
return true;
}
public boolean twoTwo(int[] nums) {
for(int i = 0;i<nums.length;i++)
if(nums[i]==2 && !isTwoBeforeOrAfter(nums,i))
return false;
return true;
}
private boolean isTwoBeforeOrAfter(int[] nums,int i){
return i+1<nums.length && nums[i+1]==2 || i-1>=0 && nums[i-1]==2;
}
public boolean twoTwo(int[] nums) {
float two = 0;
double count = 0;
for (int i = 0; i < nums.length; i++) {
if (i < nums.length - 2 && nums[i] == 2 && nums[i + 1] == 2 && nums[i + 2] == 2) {
return true;
}
if (i < nums.length - 1 && nums[i] == 2 && nums[i + 1] == 2) {
count++; //count the pair
}
if (nums[i] == 2) {
two++;
}
}
return ((count * 2) == two);
//each pair contain 2 ,two"s .so pair*2=total two counts
//count
}
public boolean twoTwo(int[] nums) {
boolean two = false;
boolean result = true;
for (int i=0; i<nums.length; i++) {
if (nums[i] == 2) {
if (two) {
result = true;
} else {
result = false;
}
two = true;
} else {
two = false;
}
}
return result;
}
Here's my solution. Enjoy.
public boolean twoTwo(int[] nums)
{
//If the length is 2 or more
if (nums.length >= 2)
{
//If the last char is a 2, but the one before it is not a char, we return false;
if (nums[nums.length - 1] == 2 && nums[nums.length - 2] != 2)
{
return false;
}
//If larger than three, we create a for loop to test if we have any 2s that are alone.
if (nums.length >= 3)
{
for (int i = 1; i < nums.length-1; i++)
{
//If we find a two that is alone, we return false;
if ((nums[i] == 2) && (nums[i-1] != 2 && nums[i+1] != 2))
{
return false;
}
}
}
//If we don't return false, we return true;
return true;
}
//If we have less than two characters, we return true if the length is 0, or \
//One the one number there is not a 2.
else
{
return ((nums.length == 0) || !(nums[0] == 2));
}
}
public boolean twoTwo(int[] nums) {
int len = nums.length;
Boolean check = false;
int count = 0;
for(int i=0; i<len ; i++){
if(nums[i]==2){
count++;
if((i<len-1 && nums[i+1]==2) || (i>0 && nums[i-1]==2)) check = true;
else check = false;
}
}
if(count==0) check = true;
return check;
}
public boolean twoTwo(int[] nums) {
int count = 0;
for (int i = 0; i < nums.length; i++)
if (nums[i] == 2) count++;
else if (count == 1) return false;
else count = 0;
return count != 1;
}
Every time we encounter a 2, we increase the counter of consecutive 2s.
When it's not a 2 — but the counter indicates that there was a single 2 before it —, we know we've found a lonely 2.
Otherwise the search continues, resetting the 2-counter.
easy to understand)
static boolean twoTwo(int[] nums) {
int len = nums.length;
boolean result = true;
boolean found = false;
for(int i=0; i<len; i++){
//if it not 2, no meaning to go true other if-s
if(nums[i] !=2) {found = false; continue;}
// if current element is 2 and found is true(last element is 2)
if(nums[i] ==2 && found) result = true;
// if current element is 2, but last element not
if(nums[i] ==2 && !found){
found = true;
result = false;
}
}
return result;
}
This might be easier to follow if the other suggestions confuse you..
public boolean twoTwo(int[] nums) {
int len = nums.length;
if(len == 0) return true; // no 2's to worry about
if(len == 1) return nums[0] != 2; // make sure it's not a single 2
for(int i = 1; i < len -1; i++){ // loop for each except edge cases
if(nums[i] == 2 && nums[i-1] != 2 && nums[i+1] != 2) return false; // check surrounding
}
if(nums[len - 1] == 2) return nums[len - 2] == 2; //if last num is 2 check for 2 before it
return true; // made it here it's true
}
that one was tough for me... here's mine:
public boolean twoTwo(int[] nums) {
boolean two = false, res = true;
for (int i : nums) {
if (i == 2) {
if (two)
res = true;
else {
two = true;
res = false;
}
} else {
two = false;
}
}
return res;
}
One more alternative. Here is the main idea:
Convert array into String. Add a character different from "2" at the beginning and end of the string, to avoid going out of bounds.
Look for standalone "2" - if element of the string is equal to 2, check whether chars immediately before and after are also equal to "2". If they are it means that not all "2" are adjacent, and therefore method returns false.
public boolean twoTwo(int[] nums) {
// convert array to string
String text = "";
for (int i = 0; i < nums.length; i++) {
text += String.valueOf(nums[i]);
}
text = " " + text + " ";
// find standalone "2"
for (int i = 1; i < text.length() - 1; i++) {
if (text.charAt(i) == '2' && text.charAt(i - 1) != '2' && text.charAt(i + 1)
!= '2') {
return false;
}
}
return true;
}

Cannot read repeating characters

I'm writing a code to read a string and count sets of repeating
public int countRepeatedCharacters()
{
int c = 0;
for (int i = 1; i < word.length() - 1; i++)
{
if (word.charAt(i) == word.charAt(i + 1)) // found a repetition
{
if ( word.charAt(i - 1) != word.charAt(i)) {
c++;
}
}
}
return c;
}
If I try the input
aabbcdaaaabb
I should have 4 sets of repeat decimals
aa | bb | aaaa | bb
and I know I'm not reading the first set aa because my index starts at 1. I tried fixing it around to read zero but then I tr to fix the entire loop to work with the change and I failed, is there any advice as to how to change my index or loop?
Try this code:
public int countRepeatedCharacters(String word)
{
int c = 0;
Character last = null;
bool counted = false;
for (int i = 0; i < word.length(); i++)
{
if (last != null && last.equals(word.charAt(i))) { // same as previous characted
if (!counted) { // if not counted this character yet, count it
c++;
counted = true;
}
}
else { // new char, so update last and reset counted to false
last = word.charAt(i);
counted = false
}
}
return c;
}
Edit - counted aaaa as 4, fixed to count as 1
from what I understood from your question, you want to count number of repeating sets, then this should help.
for (int i = 0; i < word.length()-1; i++){
if (word.charAt(i) == word.charAt(i + 1)){ // found a repetition
if (i==0 || word.charAt(i - 1) != word.charAt(i)) {
c++;
}
}
}
Try this----
public int countRepeatedCharacters()
{
int c = 0,x=0;
boolean charMatched=false;
for (int i = 0; i < word.length(); i++)
{
if(i==word.length()-1)
{
if (word.charAt(i-1) == word.charAt(i))
c++;
break;
}
if (word.charAt(i) == word.charAt(i + 1)) // found a repetition
{
charMatched=true;
continue;
}
if(charMatched==true)
c++;
charMatched=false;
}
return c;
}
Try this method. It counts the sets of repeating charactors.
public static void main(String[] args) {
String word = "aabbcdaaaabbc";
int c = 0;
for (int i = 0; i < word.length()-1; i++) {
// found a repetition
if (word.charAt(i) == word.charAt(i + 1)) {
int k = 0;
while((i + k + 1) < word.length()) {
if(word.charAt(i+k) == word.charAt(i + k + 1)) {
k++;
continue;
}
else {
break;
}
}
c++;
i+=k-1;
}
}
System.out.println(c);
}
You can try something like this:-
public static void main(String str[]) {
String word = "aabbcdaaaabbc";
int c = 1;
for (int i = 0; i < word.length() - 1; i++) {
if (word.charAt(i) == word.charAt(i + 1)) {
c++;
} else {
System.out.println(word.charAt(i)+ " = " +c);
c = 1;
}
}
System.out.println(word.charAt(word.length()-1)+ " = " +c);
}
You can modify this as per your needs, by removing the sysouts and other stuffs.
Using length() -1 is causing you to not consider the last character in your calculations.
This is causing you to lose the last repetitive character.
Finally, I would have done this as follows:
public static int countRepeatedCharacters(String word)
{
boolean withinRepeating = false;
int c = 0;
for (int i = 1; i < word.length(); i++)
{
if (!withinRepeating && (withinRepeating = word.charAt(i) == word.charAt(i - 1)))
c++;
else
withinRepeating = word.charAt(i) == word.charAt(i - 1);
}
return c;
}

Place a word in a 2d array

is there a way to place a word in a 2d array in a specific position? For example,i want to give the word, choose vertical or horizontal and the position ((3,3) or (3,4) or (5,6) etc) and the word will be placed in that position.This is my code for the array...
char [][] Board = new char [16][16];
for (int i = 1; i<Board.length; i++) {
if (i != 1) {
System.out.println("\t");
System.out.print(i-1);
}
for (int j = 1; j <Board.length; j++) {
if ((j == 8 && i == 8) ||(j ==9 && i == 9) ||(j == 10 && i == 10) ||(j == 2 && i == 2) )
{
Board[i][j] = '*';
System.out.print(Board[i][j]);
}
else {
if (i == 1) {
System.out.print("\t");
System.out.print(j-1);
}
else {
Board[i][j] = '_';
System.out.print("\t");
System.out.print(""+Board[i][j]);
}
}
(the * means that the word cant be placed there)
Is there a way to place a word in a 2d array in a specific position?
Yes you can implement that. The pseudo-code is something like this:
public void placeWordHorizontally(char[][] board, String word, int x, int y) {
for (int i = 0; i < word.length(); i++) {
if (y + i >= board[x].length) {
// fail ... edge of board
} else if (board[x][y + i]) == '*') {
// fail ... blocked.
} else {
board[x][y + i] = word.charAt(i);
}
}
}
and to do the vertical case you add i etcetera to the x position.
I won't give you the exact code because you'll learn more if you fill in the details yourself.

Categories

Resources