I am solving this kata on Codewars: https://www.codewars.com/kata/635fc0497dadea0030cb7936 this is my code:
public static void main(String[] args) {
int[][] ms;
ms = new int[][] {{1, 2, 3, 4},
{3, 1, 4, 2},
{4, 3, 2, 1},
{2, 4, 1, 3}};
System.out.println(count_different_matrices(ms));
}
private static final Set<int[]> registeredM = new HashSet<>();
static public int count_different_matrices(int[][] matrices) {
Arrays.stream(matrices).forEach(m -> {
if(unwrapPossibleMatrices(m).stream().noneMatch(registeredM::contains)) {
registeredM.add(m);
}});
registeredM.forEach(e -> System.out.println(Arrays.toString(e)));
return registeredM.size();
}
static private List<int[]> unwrapPossibleMatrices(int[] m) {
return Arrays.asList(new int[][]{
m,
{m[2], m[0], m[3], m[1]},
{m[3], m[2], m[1], m[0]},
{m[1], m[3], m[0], m[2]}
});
}
Output received in the console:
[1, 2, 3, 4]
[2, 4, 1, 3]
[4, 3, 2, 1]
[3, 1, 4, 2]
4
I expected output of only [1, 2, 3, 4]
, My train of thought was that contains()
should invoke a.equals(b)
where a
and b
in this example is of type int[]
and when they will be compared by equals - it will check if length and elements in the arrays match. Instead what happened (I think) was that address of the object was checked - thus, giving different results for arrays with the same elements. My question is the following: how to modify this code to check actual elements passed in arrays?
CodePudding user response:
Ok, I've changed my solution as @Pshemo pointed out (thank you :)
public static void main(String[] args) {
int[][] ms;
ms = new int[][] {{1, 2, 3, 4},
{3, 1, 4, 2},
{4, 3, 2, 1},
{2, 4, 1, 3}};
System.out.println(count_different_matrices(ms));
}
private static final Set<Row> registeredM = new HashSet<>();
static public int count_different_matrices(int[][] matrices) {
registeredM.clear();
Arrays.stream(matrices).forEach(m -> {
if(unwrapPossibleMatrices(m).stream().noneMatch(registeredM::contains)) {
registeredM.add(new Row(m));
}});
registeredM.forEach(e -> System.out.println(Arrays.toString(e.row())));
return registeredM.size();
}
private static List<Row> unwrapPossibleMatrices(int[] m) {
return Arrays.asList(
new Row(m),
new Row(new int[]{m[2], m[0], m[3], m[1]}),
new Row(new int[]{m[3], m[2], m[1], m[0]}),
new Row(new int[]{m[1], m[3], m[0], m[2]})
);
}
record Row(int[] row) {
@Override
public int hashCode() {
return Arrays.hashCode(row);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Row row1 = (Row) o;
return Arrays.equals(row, row1.row);
}
}
CodePudding user response:
You can write a Comparator that compares two int arrays.
Here's a code example.
import java.util.Comparator;
import java.util.Arrays;
public class CompareArrays {
Comparator<int[]> comparator = new Comparator<>() {
public int compare(int[] a1, int[] a2) {
if (a1.length != a2.length)
return a1.length - a2.length;
for (int i = 0; i < a1.length; i ) {
if (a1[i] != a2[i])
return a1[i] - a2[i];
}
return 0;
}
};
public void test(int[] a, int[] b) {
System.out.println("Array1: " Arrays.stream(a).boxed().toList());
System.out.println("Array2: " Arrays.stream(b).boxed().toList());
System.out.println(comparator.compare(a, b) == 0 ? "Array1 == Array2" : "Array1 != Array2");
}
public static void main(String[] args) {
CompareArrays program = new CompareArrays();
int[] a = {1, 2, 3, 4};
int[] b = {1, 2, 3, 4};
int[] c = {1, 2, 3};
int[] d = {4, 3, 2, 1};
int[] e = {1, 2, 3, 4, 5};
int[] f = {1, 2, 4, 3};
program.test(a, b);
System.out.println();
program.test(a, c);
System.out.println();
program.test(a, d);
System.out.println();
program.test(a, e);
System.out.println();
program.test(a, f);
}
}
Here's the output after we compile and run.
% javac CompareArrays.java
% java CompareArrays
Array1: [1, 2, 3, 4]
Array2: [1, 2, 3, 4]
Array1 == Array2
Array1: [1, 2, 3, 4]
Array2: [1, 2, 3]
Array1 != Array2
Array1: [1, 2, 3, 4]
Array2: [4, 3, 2, 1]
Array1 != Array2
Array1: [1, 2, 3, 4]
Array2: [1, 2, 3, 4, 5]
Array1 != Array2
Array1: [1, 2, 3, 4]
Array2: [1, 2, 4, 3]
Array1 != Array2
This is one way of doing it. There are other ways.
As you pointed out, the == operator compares the memory addresses of two objects. So if you create two int arrays {1, 2, 3, 4}, they will have different memory addresses, even though both arrays contain the same numbers.
In addition, you can also use the Arrays.equals method.
I just discovered the Arrays.equals and the Arrays.toString methods.
Here is a code example:
import java.util.Arrays;
public class ArraysTest {
public void run() {
int[] a = {1, 2, 3, 4};
int[] b = {1, 2, 3, 4};
int[] c = {1, 2, 3};
int[] d = {4, 3, 2, 1};
int[] e = {1, 2, 3, 4, 5};
int[] f = {1, 2, 4, 3};
test(a, b);
System.out.println();
test(a, c);
System.out.println();
test(a, d);
System.out.println();
test(a, e);
System.out.println();
test(a, f);
}
public void test(int[] a, int[] b) {
System.out.println("Array1: " Arrays.toString(a));
System.out.println("Array2: " Arrays.toString(b));
System.out.println(Arrays.equals(a, b) ? "Array1 == Array2" : "Array1 != Array2");
}
public static void main(String[] args) {
ArraysTest program = new ArraysTest();
program.run();
}
}
Here is the output after we compile and run the program. (With later versions of Java we can do this in one step.)
% java ArraysTest.java
Array1: [1, 2, 3, 4]
Array2: [1, 2, 3, 4]
Array1 == Array2
Array1: [1, 2, 3, 4]
Array2: [1, 2, 3]
Array1 != Array2
Array1: [1, 2, 3, 4]
Array2: [4, 3, 2, 1]
Array1 != Array2
Array1: [1, 2, 3, 4]
Array2: [1, 2, 3, 4, 5]
Array1 != Array2
Array1: [1, 2, 3, 4]
Array2: [1, 2, 4, 3]
Array1 != Array2
So you can see that the Arrays.equals(int[], int[])
and the Arrays.toString(int[])
methods are very useful.
The java.util.Arrays
class gives us an efficient way of comparing two int arrays (as well as any two primitive arrays).