Issue
I have tried many times to fix the failure from the method void sameNumbers()
and still I have not found a solution.
The Junit failures: junit output
The problem is, when the first array is [1]
and the second one is [0, 1]
it returns true
, instead of false
.
Can someone please explain and help me to fix this ?
Thank you.
public class SameNumbers {
public static boolean sameNumbers(int[] values1, int[] values2) {
Arrays.sort(values1);
Arrays.sort(values2);
boolean found = false;
if (values1.length == 0 && values2.length == 0) {
found = true;
} else if (values1.length == 0 && values2.length > 0 || values1.length > 0 && values2.length == 0) {
found = false;
} else if (Arrays.equals(values1, values2)) {
found = true;
} else if (values1.length > 0 && values2.length > 1 || values1.length > 1 && values2.length > 0) {
for (int i = 0; i < values1.length; i++) {
for (int k = 0; k < values2.length; k++) {
if (values1[i] == values2[k]) {
found = true;
} else {
found = false;
}
}
}
}
return found;
}
}
class SameNumbersTest {
static final int nbrTests = 20;
private Random random = new Random();
@Test
void sameNumbers1() {
Assertions.assertEquals(true, SameNumbers.sameNumbers(new int[] {}, new int[] {}),
"SameNumbers.sameNumbers(new int[]{}, new int[]{})");
}
@Test
void sameNumbers2() {
for (int i = 0; i < nbrTests; i++) {
int r = random.nextInt(20);
Assertions.assertFalse(SameNumbers.sameNumbers(new int[] {}, new int[] { r }),
"SameNumbers.sameNumbers(new int[]{}, new int[]{r})");
Assertions.assertFalse(SameNumbers.sameNumbers(new int[] { r }, new int[] {}),
"SameNumbers.sameNumbers(new int[]{r}, new int[]{})");
Assertions.assertTrue(SameNumbers.sameNumbers(new int[] { r }, new int[] { r }),
"SameNumbers.sameNumbers(new int[]{r}, new int[]{r})");
}
}
@Test
void sameNumbers3() {
for (int i = 0; i < nbrTests; i++) {
int r = random.nextInt(20);
if (r != 1) {
Assertions.assertFalse(SameNumbers.sameNumbers(new int[] { 1 }, new int[] { r, 1 }),
"SameNumbers.sameNumbers(new int[]{1}, new int[]{r, 1})");
Assertions.assertFalse(SameNumbers.sameNumbers(new int[] { r, 1 }, new int[] { 1 }),
"SameNumbers.sameNumbers(new int[]{r, 1}, new " + "int[]{1})");
} else {
Assertions.assertTrue(SameNumbers.sameNumbers(new int[] { 1 }, new int[] { r, 1 }),
"SameNumbers.sameNumbers(new int[]{1}, new int[]{r, 1})");
Assertions.assertTrue(SameNumbers.sameNumbers(new int[] { r, 1 }, new int[] { 1 }),
"SameNumbers.sameNumbers(new int[]{r, 1}, new int[]{1})");
}
}
}
@Test
void sameNumbers4() {
Assertions.assertTrue(SameNumbers.sameNumbers(new int[] { 1, 2, 3 }, new int[] { 3, 2, 1 }),
"SameNumbers.sameNumbers(new int[]{1, 2, 3}, new int[]{3, 2, 1})");
Assertions.assertTrue(SameNumbers.sameNumbers(new int[] { 1, 2, 3 }, new int[] { 3, 3, 2, 1 }),
"SameNumbers.sameNumbers(new int[]{1, 2, 3}, new int[]{3, 3, 2, 1})");
Assertions.assertFalse(SameNumbers.sameNumbers(new int[] { 1, 2, 3 }, new int[] { 3, 4, 2, 1 }),
"ameNumbers.sameNumbers(new int[]{1, 2, 3}, new int[]{3, 4, 2, 1})");
Assertions.assertTrue(SameNumbers.sameNumbers(new int[] { 1, 2 }, new int[] { 2, 1, 1 }),
"SameNumbers.sameNumbers(new int[]{1, 2}, new int[]{2, 1, 1})");
Assertions.assertTrue(SameNumbers.sameNumbers(new int[] { 1, 2, 2 }, new int[] { 2, 1, 1 }),
"SameNumbers.sameNumbers(new int[]{1, 2, 2}, new int[]{2, 1, 1})");
}
}
Solution
These loops cannot put a meaningful value in found.
for (int i = 0; i < values1.length; i++) {
for (int k = 0; k < values2.length; k++) {
if (values1[i] == values2[k]) {
found = true;
} else {
found = false;
}
}
}
Could be written as
found = values1[values1.length - 1] == values2[values2.length - 1];
You intended, something like the following, which checks that values1 is a subset of values2.
WRONG:
found = true;
for (int i = 0; i < values1.length; i++) {
found = false;
for (int k = 0; k < values2.length; k++) {
if (values1[i] == values2[k]) {
found = true;
break;
}
}
if (!found) {
break;
}
}
As you sorted a better algorithm would be:
public static boolean sameNumbers(int[] values1, int[] values2) {
values1 = IntStream.of(values1).sorted().distinct().toArray();
values2 = IntStream.of(values2).sorted().distinct().toArray();
if (values1.length != values2.length) {
return false;
}
for (int i = 0; i < values1.length; ++i) {
if (values1[i] != values2[i]) {
return false;
}
}
return true;
}
Or
public static boolean sameNumbers(int[] values1, int[] values2) {
Arrays.sort(values1);
Arrays.sort(values2);
int i1 = 0;
int i2 = 0;
while (i1 < values1.length && i2 < values2.length) {
if (values1[i1++] != values2[i2++]) {
return false;
}
while (values1[i1] == values1[i1 - 1] { // Repetitions in values1
++i1;
}
while (values1[i2] == values1[i2 - 1] { // Repetitions in values1
++i2;
}
}
return i1 == values1.length && i2 == values2.length;
}
Or
public static boolean sameNumbers(int[] values1, int[] values2) {
values1 = IntStream.of(values1).sorted().distinct().toArray();
values2 = IntStream.of(values2).sorted().distinct().toArray();
return Arrays.equals(values1, values2);
}
On test failure, the test may be wrong.
Answered By - Joop Eggen
Answer Checked By - Gilberto Lyons (JavaFixing Admin)