I am trying to work out a solution to the CodeWars challenge Catching Car Mileage Numbers:
Write the function that parses the mileage number input, and returns a 2 if the number is "interesting" (see below), a 1 if an interesting number occurs within the next two miles, or a 0 if the number is not interesting.
Interesting numbers are 3-or-more digit numbers that meet one or more of the following criteria:
- Any digit followed by all zeros: 100, 90000
- Every digit is the same number: 1111
- The digits are sequential, incementing†: 1234
- The digits are sequential, decrementing‡: 4321
- The digits are a palindrome: 1221 or 73837
- The digits match one of the values in the
awesomePhrases
array† For incrementing sequences, 0 should come after 9, and not before 1, as in 7890.
‡ For decrementing sequences, 0 should come after 1, and not before 9, as in 3210.
I can pass all tests in the first batch, but fail to pass the second batch.
Any feedback would be very much appreciated, not only on a possible solution but also to the way I'm thinking about the exercise.
public static int isInteresting(int number, int[] awesomePhrases) {
for (int offSet = 0; offSet <= 2; offSet ) {
int testNumber = number;
testNumber = offSet;
boolean isYellow = testNumber != number;
int yellowOffset = 0;
if (isYellow) {
yellowOffset = 1;
}
//check three or more digit number
boolean greaterThan99 = testNumber > 99;
int[] numbers = Integer.toString(testNumber).chars().map(c -> c - '0').toArray();
int zeroCounter = 0;
int identicalCounter = 0;
int incrementingCounter = 0;
int decrementingCounter = 0;
int palindromeCounter = 0;
boolean endsInZero = numbers[numbers.length - 1] == 0;
for (int i = 0; i < numbers.length; i ) {
//check digit followed by zeros
if (numbers[i] == 0) {
zeroCounter ;
}
if (i 1 < numbers.length) {
//check every digit is the same
if (numbers[i] == numbers[i 1]) identicalCounter ;
//check ascending order
if (numbers[i 1] - numbers[i] == 1) incrementingCounter ;
//check descending order
if (numbers[i] - numbers[i 1] == 1) decrementingCounter ;
}
}
if (greaterThan99) {
//check awesomePhrases
for (int phrase : awesomePhrases) {
if (phrase == testNumber) return 2 - yellowOffset;
}
//check palindrome
int reversedIndex = numbers.length - 1;
for (int i = 0; i < numbers.length; i ) {
if (numbers[reversedIndex] == numbers[i]) {
palindromeCounter ;
}
reversedIndex--;
}
if (zeroCounter == numbers.length - 1) return 2 - yellowOffset;
if (identicalCounter == numbers.length - 1) return 2 - yellowOffset;
if (incrementingCounter == numbers.length - 1) return 2 - yellowOffset;
if (incrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
if (decrementingCounter == numbers.length - 1) return 2 - yellowOffset;
if (decrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
if (palindromeCounter == numbers.length) return 2 - yellowOffset;
}
}
return 0;
}
I've tried pretty much all I know but to no result, all the tests I try pass, would love to know what I'm doing wrong.
CodePudding user response:
The problem is in how your code tests for increasing sequences that end in a zero. It is not enough to test that the sequence has n-2 increments and the last digit is a zero, because that will give a false positive on numbers like 6780. It is required that the one-but-last digit is a 9.
A similar issue exist for the decreasing sequence logic, however, there you would not need a special test for an ending zero at all. This condition is covered by counting n-1 decrements, where the ending could be a 1 followed by a zero. There is no special case to be handled here.
To fix the first problem, I would suggest you not only check whether the last digit is a zero, but whether the last two digits are 9 and 0, or in other words, that the number modulo 100 is equal to 90.
You could replace this:
boolean endsInZero = numbers[numbers.length - 1] == 0;
by this:
boolean endsInNinety = testNumber % 100 == 90;
and then replace:
if (incrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
by:
if (incrementingCounter == numbers.length - 2 && endsInNinety) return 2 - yellowOffset;
and finally remove this test:
if (decrementingCounter == numbers.length - 2 && endsInZero) return 2 - yellowOffset;
This will fix it.
Note that it can be helpful to have your function print the input it gets, so that when a test fails, at least you can know for which input there was a problem:
System.out.println("input " number);