So I have this recursive method that searches a 4x4 "board" for a word (think boggle except it only looks above, below, left, and right of the current letter). It gets passed an index (the current letter it is searching for from a given word), and the row and column to search around. The first if statement takes care of the first letter, and always works. The next else if statement doesn't work, and I'm not sure why. Any help is appreciated as to why. secondArray is used in another part of the program when it is displayed.
private boolean verifyWord(int index, int row, int column) {
System.out.println(index + " " + row + " " +column);
if (index == 0) {
for (int i = 0; i < letterArray.length; i++) {
for (int i2 = 0; i2 < letterArray[0].length; i2++) {
if (letterArray[i][i2] == wordToFind.charAt(index)) {
secondArray[i][i2] = true;
verifyWord(index+1, i, i2);
}
}
}
} else if (index > 0 && index < wordToFind.length()) {
// check above row
if (row+1 < row) {
if (letterArray[row+1][column] == wordToFind.charAt(index)) {
secondArray[row+1][column] = true;
verifyWord(index+1, row+1, column);
}
}
//check below row
if (row-1 >= 0) {
if (letterArray[row-1][column] == wordToFind.charAt(index)) {
secondArray[row-1][column] = true;
verifyWord(index+1, row-1, column);
}
}
//check left column
if (column-1 >= 0) {
if (letterArray[row][column-1] == wordToFind.charAt(index)) {
secondArray[row][column-1] = true;
verifyWord(index+1, row, column-1);
}
}
//check right column
if (column+1 < letterArray[0].length) {
if (letterArray[row][column+1] == wordToFind.charAt(index)) {
secondArray[row][column+1] = true;
verifyWord(index+1, row, column+1);
}
}
} else {
boolCheck = true;
}
return boolCheck;
}
The first condition if(row+1 < row) in your else if(index > 0 && index < wordToFind.length()) would never be evaluated to true (x+1 is always bigger than x).
You probably want it to be if(row+1 < letterArray.length)
Related
I am trying to solve a boggle word checker problem, I am almost there but I need some help with the logic.
Boggle word checker takes a 2d array and a string and I want to determine whether that string is a valid boggle word returning either true or false. So valid guesses are strings which can be formed by connecting adjacent cells (horizontally, vertically, or diagonally) without re-using any previously used cells.
For example EAR is correct but EARS is not.
From what I can tell, it seems to work properly until it gets to the last letter and then I am having issues with it returning correctly T/F. I tried using an if statement so that it would stop the recursive call but it doesn't seem to be working. Any advice on how to figure it out would be amazing!
final private static char[][] board = {
{'E','A','R','A'},
{'N','L','E','C'},
{'I','A','I','S'},
{'B','Y','O','R'}
}
public class Boggle {
char[][] board;
String word;
public Boggle(final char[][] board, final String word) {
this.board = board;
this.word = word;
}
public boolean checkit() {
//make string array
//iterated through board
//if word[0] == board value
//check -> see if value above beloow left right is a match to word[1]
System.out.println("word: "+word);
char[] charArr = word.toCharArray();
int index = 0;
boolean valid = false;
for(int row=0; row< board.length; row++) {
for(int col=0; col<board[0].length; col++) {
if(board[row][col] == charArr[index]) {
return check(board, charArr, row, col, index);
}
}
}
return valid;
}
public boolean check(char[][] board, char[] charArr, int row, int col, int index) {
index++;
//while index< charArr.length, keep searching for matches
System.out.println("index: "+index + " chararr.length: "+charArr.length);
if(index >= charArr.length) return true;
else if(index < charArr.length) {
System.out.println("here");
//check up
if(row-1 >= 0) {
if(board[row-1][col] == charArr[index]) {
check(board, charArr, row-1, col, index);
}
}
//check up/right (diagonal)
else if((row-1 >= 0) && (col+1 < board[0].length)) {
if(board[row-1][col+1] == charArr[index]) {
check(board, charArr, row-1, col+1, index);
}
}
//check right
else if(col+1 < board[0].length) {
if(board[row][col+1] == charArr[index]) {
System.out.println("right");
check(board, charArr, row, col+1, index);
}
}
//check right/down (diagonal)
else if((col+1 < board[0].length) && (row+1 < board.length)) {
if(board[row+1][col+1] == charArr[index]) {
check(board, charArr, row+1, col+1, index);
}
}
//check down
else if(row+1 < board.length) {
if(board[row+1][col] == charArr[index]) {
check(board, charArr, row+1, col, index);
}
}
//check down/left (diagonal)
else if((col-1 >= 0) && (row+1 < board.length)) {
if(board[row+1][col-1] == charArr[index]) {
check(board, charArr, row+1, col-1, index);
}
}
//check left
else if(col-1 >= 0) {
if(board[row][col-1] == charArr[index]) {
check(board, charArr, row, col-1, index);
}
}
//check left/up (diagonal)
else if((col-1 >= 0) && (row-1 >= 0)) {
if(board[row-1][col-1] == charArr[index]) {
check(board, charArr, row-1, col-1, index);
}
}
//no match
System.out.println("false section");
return false;
} //end while
return false;
}
}
Problems I see include:
You don't look at the return result of check().
You allow a word to use the same letter twice.
The following code is redundant.
if(index >= charArr.length) return true;
else if(index < charArr.length) {
If it gets past the first line, we know the condition must pass, so there is no need to check it again.
I keep receiving an ArrayIndexOutOfBounds on the line directly after the for loop. I would also wondering how I could continue to loop the matrix to iterate the row or column until the target is reached.
In the given matrix, I want to start in the bottom left hand corner. If the target value is less than the selected number then the row moves up. If the target value is greater than the selected number then column moves one to the right.
public static void optimizedSearch(int matrix[][], int array_size, int target) {
int row = 0;
int col = array_size-1;
boolean found = false;
int comparison_counter = 0;
int end = array_size * 2;
//while (!found) {
for (int i = 0; i < 100 && !found; i++) {
if (matrix[row][col] < target ) {
row++;
comparison_counter++;
} else if (matrix[row][col] > target) {
col--;
comparison_counter++;
} else if (matrix[row][col] == target) {
found = true;
} else if ((i == end) && (found == false)) {
found=false;
}
}// end for loop
if (found == true) {
System.out.println(target + " found in " + comparison_counter + " number of comparisons using optimized search");
} else
System.out.println(target + " not found in " + comparison_counter + " number of comparisons using optimized search");
} //end optimizedSearch
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.
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;
}
To clarify I only wanted one or two for loops to help me on my way, preferably in the same style as I had used in the vertical :)
I'm making a game using a 2D array, and I need a check that tests if at the current position (indicated by a green square) the character there is part of a diagonal sequence of "l" more of the character.
public static boolean diagonals(char[][] b, int row, int col, int l) {
int counter = 1; // because we start from the current position
char charAtPosition = b[row][col];
int numRows = b.length;
int numCols = b[0].length;
int topleft = 0;
int topright = 0;
int bottomleft = 0;
int bottomright = 0;
for (int i=row-1,j=col-1;i>=0 && j>=0;i--,j--) {
if (b[i][j]==charAtPosition) {
topleft++;
} else {
break;
}
}
for (int i=row-1,j=col+1;i>=0 && j<=numCols;i--,j++) {
if (b[i][j]==charAtPosition) {
topright++;
} else {
break;
}
}
for (int i=row+1,j=col-1;i<=numRows && j>=0;i++,j--) {
if (b[i][j]==charAtPosition) {
bottomleft++;
} else {
break;
}
}
for (int i=row+1,j=col+1;i<=numRows && j<=numCols;i++,j++) {
if (b[i][j]==charAtPosition) {
bottomright++;
} else {
break;
}
}
return topleft + bottomright + 1 >= l || topright + bottomleft + 1 >= l; //in this case l is 5
}
The idea is that we walk in four directions and count the steps. This may not be the most efficient implementation, but at least it looks neat and easy to understand.
Here's the function, it works. The explanation is in the comments in the code, but if you find anything confusing let me know and I'll explain it.
public static boolean diagonals(char[][] b, int row, int col, int l) {
int forwardCounter = 1; // this counts top right to bottom left
int backCounter = 1; // this counts top left to bottom right
int distance = 1;
// 0 = topleft, 1 = topright, 2 = bottomleft, 3 = bottomright
boolean[] checks = new boolean[]{true, true, true, true};
char charAtPosition = b[row][col];
while(checks[0] || checks[1] || checks[2] || checks[3]) {
for(int i = 0; i < 4; i++) {
if(checks[i]) {
// This looks confusing but it's simply just converting i into
// The four different directions
checks[i] = checkSquare(b, row + (i < 2 ? -distance : distance),
col + (i % 2 == 0 ? -distance : distance), charAtPosition);
if(checks[i]) {
// If top left or bottom right
if(i % 3 == 0) {
backCounter++;
} else {
forwardCounter++;
}
}
}
}
if (forwardCounter >= l || backCounter >= l) return true;
distance++;
}
return false;
}
private static boolean checkSquare(char[][] b, int row, int col, char check) {
if(row < 0 || row >= b.length) return false;
if(col < 0 || col >= b[0].length) return false;
return check == b[row][col];
}