Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am writing a program, in which, I have a method called "equals" to test whether two 2-dimensional arrays are "equal" to each other. equals returns whether the two args are equivalent in the sense that
If both args are null, return true
If one arg is null and the other isn't, return false;
If the 2 arrays have a different number of rows, return false
else, return whether each element in arr1 is equivalent to the corresponding element in arr2 in the sense that both elements are null, or both elements refer to arrays with the same number of ints with the same values in the same order.
equals method definition:
public static boolean equals( int[][] arr1, int[][] arr2){
//both are null references
if(arr1 == null && arr2 == null)
return true;
//only one is a null reference
if ((arr1 == null && arr2 != null) || (arr1 == null && arr2 != null))
return false;
//number of rows not identical
if( arr1.length != arr2.length )
return false;
for(int i = 0 ; i < arr1.length; i++){ //checking row equivalence
if(arr1[i] == null && arr2[i]==null){ //both null
continue;
}
if(arr1[i] == null || arr2[i] == null) //one is null
return false;
else if(arr1[i].length != arr2[i].length){
return false;
}
else{
for(int j = 0; j < arr1[i].length; i++){ //#of columns equal, compare them
System.out.println(i + "," + j); //helps debug
if(arr1[i][j] != arr2[i][j])
return false;
}
}
}
return true;
} //equals
When I call
equals( new int[][]{{1,2},{3,4},null}, new int[][]{{1,2},null,{3,4}} )
my program crashes, throwing the NullPointerException.
Eclipse says that it failed at this line:
if(arr1[i][j] != arr2[i][j])
The problem is, as far as I can tell, my program shouldn't be entering the enclosing for-loop where this line is located to begin with. It should return false at this point:
if(arr1[i] == null || arr2[i] == null) //one is null
return false;
What am I doing wrong here? Thank you.
You have a defect here,
if ((arr1 == null && arr2 != null) || (arr1 == null && arr2 != null))
should be
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null))
because otherwise you aren't testing both are arr1 and arr2. However, I would prefer Arrays.deepEquals(Object[], Object[]) which returns true if the two specified arrays are deeply equal to one another... Two array references are considered deeply equal if both are null, or if they refer to arrays that contain the same number of elements and all corresponding pairs of elements in the two arrays are deeply equal. like
public static boolean equals(int[][] arr1, int[][] arr2) {
return Arrays.deepEquals(arr1, arr2);
}
Related
I've been trying to implement a Comparator class which should order a list based on weight of position. I will explain what I should accomplish.
Suppose I have an ArrayList<T>. This array list has always a fixed size, filling other slot with null values.
//fixed size = 3
T myObj1, myObj2;
[myObj1, null, myObj2];
In this example, myObj2 < myObj1, since it is stored in a slot whose position value is less than the first.
An ordering comparator should give this output:
//fixed size = 3
T myObj1, myObj2;
[myObj1, myObj2, null];
Other examples:
//fixed size = 7;
T myObj1, myObj2, myObj3, myObj4;
INPUT = [myObj1, null, null, myObj4, myObj3, myObj2, null];
RESULT = [myObj1, myObj4, myObj3, myObj2, null, null, null];
I thought about using aComparator<T>(The T is a specific class, it does not need to be general actually); is there a way to replicate such behaviour?
You could always make nulls return > 0 in a comparator
if (one == null && two == null) {
return 0;
} else if (two == null) {
return -1;
} if (one == null) {
return 1;
} else {
//Compare logic...
}
This says nulls are "bigger" than non-null values
Instead of writing your own comparator logic, it is usually simpler to use one of the helper methods such as Comparator.comparing.
> List<Integer> foo = Arrays.asList(1, null, 2, null, 1, null);
> Collections.sort(foo, Comparator.comparing(x -> x == null ? 1 : 0));
> foo
[1, 2, 1, null, null, null]
This way the sort is done as if non-null elements are all 0, and nulls are 1, so the nulls will appear after the non-nulls when they are sorted. The non-null elements will remain in their original order, because Collections.sort is stable.
For this specific case as #Zabuza notes, the helper method Comparator.nullsLast does exactly the right thing; the argument is null because there is no "fallback" comparator we want to use for non-null elements.
> Collections.sort(foo, Comparator.nullsLast(null));
That said, this solution takes O(n log n) time for a list of length n, when a two-pointer solution could solve the same problem in O(n) time.
For anyone in need, I figured it out thanks to #tomgeraghty3
public class TComparator implements Comparator<T> {
public int compare(T r1, T r2) {
if (r1 == null && r2 == null) {
return 0;
} else if (r2 == null) {
return -1;
} if (r1 == null) {
return 1;
} else {
return 1;
}
}
}
private Comparator<Entity> spriteSorter = new Comparator<Entity>() {
public int compare(Entity e0, Entity e1) {
if (e0 == null || e1 == null) return -1; //was 0
if (e1.getY() < e0.getY()) return +1;
if (e1.getY() > e0.getY()) return -1;
return -1; //was 0
}
};
I have read many articles about this one, but I still don't know how to solve this little problem:
This is the core that works:
if (e1.getY() < e0.getY()) return +1;
if (e1.getY() > e0.getY()) return -1;
But sometimes (I have to deal with many houndred entities which are being added and removed from a concurrent array list very often in a second) one of the entities is null. Therefore I have to check this inside this comparator.
But then I violate this general contract, once one of the two objects is null.
Any idea how I can solve this? Please help! :)
Your comparator, if called with c.compare(null, null), will compare null < null, even though they are equal. Further, it breaks the rule for inverses, which is that sgn(compare(a, b)) == -sgn(compare(b, a)), that is, comparing two things backwards returns the opposite of comparing them forwards. You can fix all this simply by treating null as "negative infinity," that is enforcing that null < a for all nonnull a and null == null.
public int compare(Entity l, Entity r) {
if (Objects.equals(l, r)) return 0; // Handles normal and null equality
else if(l == null) return -1; // Enforce null < a ∀ nonnull a
else if(r == null) return +1; // Enforce a > null ∀ nonnull a
else return Integer.compare(l.getY(), r.getY()); // Base comparison
}
I'm new to java.
Can anybody tell me that is the easiest way to compare two string except one character?
like:
'test' 'text' //only one character different
should return true
==============================
like input:
'test' 'txxt' //two character different return false
should return false
I know we can compare with a for loop. Is there any other way to do that?
Thx for your help. : )
Assuming the Strings are the same size, here is a solution. This solution will need to be altered slightly for uneven String lengths
boolean compareStrings(String str1, String str2) {
if (str1.length() != str2.length())
return false;
int differences = 0;
for (int i = 0; i < str1.length(); i++) {
if(str1.charAt(i) != str2.charAt(i))
if(++differences > 1)
return false;
}
//if the execution is here, then there are 0, or 1 differences, so return true
return true;
}
Try this method.
It should work for every string combination but, depending on usage, maybe a performance tuning is needed.
public static boolean compare(String s1, String s2) {
if((s1 != null && s2==null) || (s1 == null && s2!=null)){
//exact one is null
return false;
}
if((s1 == null && s2==null) || s1.equals(s2)){
//both are null or equal
return true;
}
if(Math.abs(s1.length() - s2.length()) > 1){
//A different length of more than one is more than one difference, right ?
return false;
}
//Here you have two different strings. Maybe one is a character larger than the other.
if(s1.length() != s2.length()) {
//They differ in length, so they must be equal in the first minLen charcaters.
int minLen = Math.min(s1.length(), s2.length());
return s1.substring(0,minLen).equals(s2.substring(0,minLen));
}
//Here you have two different strings of the same length.
int diff = 0;
for(int i = 0; i < s1.length() && diff < 2; i++){
if(s1.charAt(i) != s2.charAt(i)){
diff++;
}
}
return diff < 2;
}
public boolean checkWin() {
if(states[0][0][0] == 1 && states[0][0][1] == 1 && states[0][0][2] ==1 && states[0][0][3] ==1) { // Checks 0th layer, 0th row
return true;
}
else if (states[0][1][0] == 1 && states[0][1][1] == 1 && states[0][1][2] ==1 && states[0][1][3] ==1) { // Checks 0th layer, 1st row
return true;
}
else if (states[0][2][0] == 1 && states[0][2][1] == 1 && states[0][2][2] ==1 && states[0][2][3] ==1) { // Checks 0th layer, 2nd row
return true;
}
else if (states[0][3][0] == 1 && states[0][3][1] == 1 && states[0][3][2] ==1 && states[0][3][3] ==1) { // Checks 0th layer, 3rd row
return true;
}
}
This code is hard coded to check the 0 th layer, and the 4 rows on that layer. I could hard code the rest but of course that would be very time consuming and bad code. When I try and make a loop it stops after three clicks
public boolean checkWin() {
for (int i=0; i<=3; i++) {
if(states[0][0][i] == 1){ // Checks 0th layer, all rows
return true;
}
}
return false;
}
This is how I tried to make the loop, but it doesn't work.
This game is a nice example of how a data driven approach can simplify our code. Consider:
there are 64 cells, that can be empty or contain a token; the number of tokens depends on the number of players. This can be represented as a one dimensional array of 64 elements.
the cells are in 76 rows. This can be represented as a array of 76 rows of 4, each cell containing a subscript for an element in the first array. (In C or C++ you could also store pointers, in Java you can store references).
To check for a winning row, you can then just iterate through the 76 rows, and check if every cell in a row of the first array has the value you assigned to one player or the other.
Your current code checks only for rows in the third dimension. You should check the other dimensions as well:
for(int i = 0;i < 4;i++) {
for(int j = 0;j < 4;j++) {
if(
(states[i][j][0] == 1 && states[i][j][1] == 1 && states[i][j][2] == 1 && states[i][j][3] == 1) ||
(states[i][0][j] == 1 && states[i][1][j] == 1 && states[i][2][j] == 1 && states[i][3][j] == 1) ||
(states[0][i][j] == 1 && states[1][i][j] == 1 && states[2][i][j] == 1 && states[3][i][j] == 1)) {
return true;
}
}
}
You could make it more abstract than this by looping also over the last dimension, but that'd require boolean variables or break/continue statements so I think this is about as clear as the code is going to get.
You need to rewrite you loop like so:
public boolean checkWin() {
for (int layer=0; layer<=3; layer++) {
for (int row=0; row<=3; row++) {
if(states[layer][row][0] == 1){
return true;
}
}
}
return false;
}
This logic checks only for row based wins. Note however that in a TicTacToe, you also need to check for Column based win and diagonal win.
I'm having an issue with a mock game of Tic tac toe. I'm using a two-dimensional array to represent the playing board, and have instantiated it as follows. It's required that I use a char type array. I realize that I shouldn't have to specify that each index is null, as that's the default for char, but I thought I would give it a try.
public TicTacToe2D()
{
board = new char[3][3];
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
board[j] = null;
}
board[i] = null;
}
}
Here I'm checking for a win condition, seeing if indexes are equal to each other and not null (the default) though I have attempted using ' ' for my array initial value. In that case I got the error: "incompatible types: char cannot be converted to char[]"
public char isWin()
{
//Check for row wins
if (board[0][0] == board[0][1] && board[0][1] == board[0][2] && board[0][0] != null)
return true;
if (board[1][0]==board[1][1] && board[1][1]==board[1][2] && board[1][0] != null)
return true;
if (board[2][0]==board[2][1] && board[2][1]==board[2][2] && board[2][0] != null)
return true;
//Check for column wins
if (board[0][0]==board[1][0] && board[1][0]==board[2][0] && board[0][0] != null)
return true;
if (board[0][1]==board[1][1] && board[1][1]==board[2][1] && board[0][1] != null)
return true;
if (board[0][2]==board[1][2] && board[1][2]==board[2][2] && board[0][2] != null)
return true;
//Check for diagonal wins
if (board[0][0]==board[1][1] && board[1][1]==board[2][2] && board[0][0] != null)
return true;
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != 0)
return true;
else return false;
}
When checking if an index is null I get the error "incomparable types: char and "
Any help would be greatly appreciated!
The datatype char is primitive, so it can't be null. But the default value is the null character, \0 (or \u0000). JLS Section 4.12.5 gives default values:
For type char, the default value is the null character, that is, '\u0000'.
Try comparing it to \0 or \u0000 instead of null.
a char is not an object, it's a primitive type.
that means that a char is like an integer, or float, or Boolean, that have a fixed length and its initial value is zero (or false).
As far as I remember char is an 8bit, but I might be wrong. Said all that, a char you can compare to a letter, for example: 'a' or with an actual number, for example 0 or 1.
board is declared as char[][]. It is thus an array of char arrays. So board[i] is a char array (a row of your board). And board[i][j] is a char (the value of a cell of your board).
The default value of each cell of such a 2D array is 0. Not null. A primitive type can't be null.