I checked on the stackExchange description, and algorithm questions are one of the allowed topics. So here goes.
Given an input of a range, where begin and ending number
Here's my solution and an algorithm with complexity O(log n)
(n is the end of the range). I believe it is the simplest one here:
Basically, split your task into these steps:
start
of the range.end
of the range.By "weaken", I mean finding the end of range that can be represented by simple regex for this specific number, for example:
145 -> 149,150 -> 199,200 -> 999,1000 -> etc.
Here's a backward one, for the end
of the range:
387 -> 380,379 -> 300,299 -> 0
Merging would be the process of noticing the overlap of 299->0 and 200->999 and combining those into 200->299.
In result, you would get this set of numbers (first list intact, second one inverted:
145, 149, 150, 199, 200, 299, 300, 379, 380, 387
Now, here is the funny part. Take the numbers in pairs, and convert them to ranges:
145-149, 150-199, 200-299, 300-379, 380-387
Or in regex:
14[5-9], 1[5-9][0-9], 2[0-9][0-9], 3[0-7][0-9], 38[0-7]
Here's how the code for the weakening
would look like:
public static int next(int num) {
//Convert to String for easier operations
final char[] chars = String.valueOf(num).toCharArray();
//Go through all digits backwards
for (int i=chars.length-1; i>=0;i--) {
//Skip the 0 changing it to 9. For example, for 190->199
if (chars[i]=='0') {
chars[i] = '9';
} else { //If any other digit is encountered, change that to 9, for example, 195->199, or with both rules: 150->199
chars[i] = '9';
break;
}
}
return Integer.parseInt(String.valueOf(chars));
}
//Same thing, but reversed. 387 -> 380, 379 -> 300, etc
public static int prev(int num) {
final char[] chars = String.valueOf(num).toCharArray();
for (int i=chars.length-1; i>=0;i--) {
if (chars[i] == '9') {
chars[i] = '0';
} else {
chars[i] = '0';
break;
}
}
return Integer.parseInt(String.valueOf(chars));
}
The rest is technical details and is easy to implement. Here's an implementation of this O(log n)
algorithm: https://ideone.com/3SCvZf
Oh, and by the way, it works with other ranges too, for example for range 1-321654
the result is:
[1-9]
[1-9][0-9]
[1-9][0-9][0-9]
[1-9][0-9][0-9][0-9]
[1-9][0-9][0-9][0-9][0-9]
[1-2][0-9][0-9][0-9][0-9][0-9]
3[0-1][0-9][0-9][0-9][0-9]
320[0-9][0-9][0-9]
321[0-5][0-9][0-9]
3216[0-4][0-9]
32165[0-4]
And for 129-131
it's:
129
13[0-1]