6
\$\begingroup\$

twinoid is defined to be an array that has exactly two even values that are adjacent to one another. For example {3, 3, 2, 6, 7} is a twinoid array because it has exactly two even values (2 and 6) and they are adjacent to one another. The following arrays are not twinoid arrays.

  • {3, 3, 2, 6, 6, 7} because it has three even values.
  • {3, 3, 2, 7, 6, 7} because the even values are not adjacent to one another.
  • {3, 8, 5, 7, 3} because it has only one even value.

I wrote Twinoid to check that given array is twinoid or not.

public class Twinoid {

public static void main(String args[]) {
    System.out.println("The result is: " + isTwinoid(new int[]{3, 3, 2, 6, 7}));
}

public static boolean isTwinoid(int[] a) {
    boolean status = false;
    int i;
    int count = 0;
    for (i = 0; i < a.length; i++) {
        if (a[i] % 2 == 0) {
            count++;
        }
    }
    if (count == 2) {
        int j;
        for (j = 0; j < a.length; j++) {
            if (a[j] % 2 == 0) {
                System.out.println(a[j]);
                break;
            }
        }
        int nextValue = a[j + 1];
        System.out.println(nextValue);
        if (nextValue % 2 == 0) {
            status = true;
        }
    } else {
        status = false;
    }
    return status;
}
}
\$\endgroup\$
0

2 Answers 2

5
\$\begingroup\$

You don't need two passes.

    boolean status = false;
    int i;
    int count = 0;
    for (i = 0; i < a.length; i++) {
        if (a[i] % 2 == 0) {
            count++;
        }
    }
    if (count == 2) {
        int j;
        for (j = 0; j < a.length; j++) {
            if (a[j] % 2 == 0) {
                System.out.println(a[j]);
                break;
            }
        }
        int nextValue = a[j + 1];
        System.out.println(nextValue);
        if (nextValue % 2 == 0) {
            status = true;
        }
    } else {
        status = false;
    }
    return status;

You can replace this with just

    int i;
    for (i = 0; i < a.length - 1; i++) {
        if (a[i] % 2 == 0) {
            i++;
            if (a[i] % 2 == 0) {
                i++;
                break;
            } else {
                return false;
            }
        }
    }

    if (i == a.length && a[i-1] % 2 != 0) {
        return false;
    }

    for (; i < a.length; i++) {
        if (a[i] % 2 == 0) {
            return false;
        }
    }

    return true;

or even shorter

    for (int i = 0; i < a.length - 1; i++) {
        if (a[i] % 2 == 0) {
            i++;
            if (a[i] % 2 == 0) {
                i++;
                for (; i < a.length; i++) {
                    if (a[i] % 2 == 0) {
                        return false;
                    }
                }

                return true;
            } else {
                return false;
            }
        }
    }

    return false;

Either of these only requires a single scan.

If they find no even numbers in the first a.length - 1 elements, they fall through and return false.

If they find an even number but the next number is odd, they return false.

If they find two even numbers and then find a third, they return false.

If they find two even numbers and every remaining number is odd, they return true.

This saves both status and count as variables.

But the shortest version that I could write was

    int evensCount = 0;
    for (int number : numbers) {
        if (number % 2 == 0) {
            evensCount++;
        } else if (evensCount > 0 && evensCount != 2) {
            return false;
        }
    }

    return evensCount == 2;

Note that I renamed a to numbers in this case. I prefer that kind of name for collections and arrays, and since I only use it once, there was less advantage to terseness.

This version only checks if numbers are even in one place. All the other versions had to do this in multiple places. I believe that makes this code DRYer as well as shorter.

This iterates through the array, counting the even numbers. For each odd number, it checks if it has seen any even numbers. If it has, it checks if it has seen exactly two. If not, it can return false. If it has seen exactly two consecutive even numbers, it keeps going. If it goes all the way through and finds exactly two even numbers, it can return true. Otherwise, it returns false.

So if it sees one even number followed by an odd number, it will abort and return false. The evensCount will be equal to 1.

If it sees three or more consecutive even numbers, it will return false once it sees the next odd number. Or when it is done iterating if the even numbers last until the end.

If it sees two consecutive even numbers and then an odd number, it will search for more even numbers. If it finds one, it will eventually return false. If it doesn't, it will return true after scanning the entire array.

You could sometimes speed it up by adding another if that checks if evensCount is greater than two. However, that will also slow it down in some situations. And of course it is more code. If time is critical, it might help. Or not. It really depends on the inputs. I omitted it because it is only sometimes better at all and I'm not sure we need to optimize to that level.

My test cases:

    System.out.println("The result is: " + isTwinoid(new int[]{3, 3, 2, 6, 5, 6, 7}));
    System.out.println("The result is: " + isTwinoid(new int[]{3, 3, 2, 6, 6, 7}));
    System.out.println("The result is: " + isTwinoid(new int[]{3, 3, 2, 7, 6, 7}));
    System.out.println("The result is: " + isTwinoid(new int[]{3, 8, 5, 7, 3}));
    System.out.println("The result is: " + isTwinoid(new int[]{3, 3, 2, 6, 7}));
    System.out.println("The result is: " + isTwinoid(new int[]{3, 3, 2, 6}));

Results:

The result is: false
The result is: false
The result is: false
The result is: false
The result is: true
The result is: true

\$\endgroup\$
0
0
\$\begingroup\$

As mdfst13 pointed out, you don't need to scan the array twice.

Actually, you may only need to check the next int after the first even one, as you can stop if it is not also even.

Otherwise, continue scanning the remainder of the array and you can stop if you find any third even number.

public class Twinoid {

    /**
     * Returns true if the array contains exactly two even values that are adjacent.
     */
    public static boolean isTwinoid(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            if (!isEven(array[i])) {
                continue;
            }
            if (!isEven(array[i + 1])) {
                return false;
            }
            return !containsEvenFromIndex(array, i + 2);
        }
        return false;
    }

    private static boolean containsEvenFromIndex(int[] array, int i) {
        while (i < array.length) {
            if (isEven(array[i])) {
                return true;
            }
            i++;
        }
        return false;
    }

    private static boolean isEven(int n) {
        return n % 2 == 0;
    }

}
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.