/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
Name of the class has to be "Main" only if the class is public.
Code has been taken from the following three sources and bundled
together for a full solution.
Algorithm - https://stackoverflow.com/a/33539325/6385674
Overall Code - https://stackoverflow.com/a/33554746/6385674
Recursion Method - https://stackoverflow.com/a/33597252/6385674
*/
class Ideone
{
protected String[] regexArray
= null; protected List<String> regexList = null;
{
Ideone ideone = new Ideone();
ideone.generateRegEx("287", "2678905");
for (String s
: ideone.
regexArray) { System.
out.
println(s
); } }
public Ideone()
{
regexList = new ArrayList<String>();
}
/**
* Return a list of regular expressions that match the numbers
* that fall within the range of the given numbers, inclusive.
* Assumes the given strings are numbers of the the same length,
* and 0-left-pads the resulting expressions, if necessary, to the
* same length.
* @param begStr
* @param endStr
*/
{
//Log Input Data.
System.
out.
println("Starting getRegex Method with String input."); System.
out.
println("Input Data is: "); System.
out.
println("Range Start : [" + begStr
+ "]"); System.
out.
println("Range End : [" + endStr
+ "]");
//Get integer range values.
System.
out.
println("Converting input string range values to integer values.");
int beg
= Integer.
parseInt(begStr
); int end
= Integer.
parseInt(endStr
);
System.
out.
println("Successfully converted input string range values to integer values.");
//Print integer values
System.
out.
println("Range Start (Int) : [" + beg
+ "]"); System.
out.
println("Range End (Int) : [" + end
+ "]");
//call common method to generate RegEx Pairs.
generateRegExCommon(beg,end,begStr.length());
}
/**
* Return a list of regular expressions that match the numbers
* that fall within the range of the given numbers, inclusive.
* @param beg
* @param end
*
**/
public void generateRegEx(int beg, int end)
{
//Log Input Data.
System.
out.
println("Starting getRegex Method with integer input."); System.
out.
println("Input Data is: "); System.
out.
println("Range Start : [" + beg
+ "]"); System.
out.
println("Range End : [" + end
+ "]");
//call common method to generate RegEx Pairs.
generateRegExCommon(beg,end,0);
}
private void generateRegExCommon(int start, int end, int stringLength)
{
//call method to generate RegEx Pairs.
System.
out.
println("Calling method to generate RegEx pairs for the input.");
List<Integer> pairs = getRegexPairsRecursion(start, end, 1);
System.
out.
println("Returned from method with a List of RegEx pairs for the input."); System.
out.
println("Total RegEx Ranges: [" + pairs.
size()/2 + "]");
System.
out.
println("Printing range values."); pairs.
forEach(s
-> System.
out.
println(s
+"")); System.
out.
println("Completed printing range values.");
printPairList(pairs);
//String length of the input is used to identify if any leading zeros need to be prepended to the RegEx pairs.
System.
out.
println("String length of input is: [" + stringLength
+ "]");
System.
out.
println("Calling method to convert range pairs to RegEx."); //regexList = toRegex(pairs, stringLength);
regexList = formatPairsToRegEx(pairs, stringLength);
System.
out.
println("Completed converting range pairs to RegEx.");
System.
out.
println("Printing RegEx list."); regexList.
forEach(s
-> System.
out.
println(s
+"")); System.
out.
println("Completed printing RegEx list.");
System.
out.
println("Converting RegEx list to an array."); regexArray
= regexList.
toArray(new String[regexList.
size()]); System.
out.
println("Completed converting RegEx list to an array.");
System.
out.
println("Printing RegEx array."); regexList.
forEach(s
-> System.
out.
println(s
+"")); System.
out.
println("Completed printing RegEx array."); }
/**
* return the list of integers that are the paired integers
* used to generate the regular expressions for the given
* range. Each pair of integers in the list -- 0,1, then 2,3,
* etc., represents a range for which a single regular expression
* is generated.
* @param start
* @param end
* @return
*/
private List<Integer> getRegexPairsRecursion(int start, int end, int recursionLevel)
{
List<Integer> pairs = null;
pairs = new ArrayList<>();
for (int i = 0; i <= recursionLevel - 1; i++)
{
printIndent += " ";
}
System.
out.
println(printIndent
+ "Entering method " + "getRegexPairsRecursion." + " Level [" + recursionLevel
+ "].");
System.
out.
println(printIndent
+ "Start Range : [" + start
+ "]"); System.
out.
println(printIndent
+ "End Range : [" + end
+ "]");
if(start == 0)
{
System.
out.
println(printIndent
+ "Range start value is 0. Add pair of zeros and set start range value to 1."); pairs.add(0);
pairs.add(0);
start = 1;
}
/*If start is greater than end of the range, return the current values in pairs.
* Apart from the special case when start value is 0, this will always be empty,
*because if start is greater than end range value, it cannot be represented using
*RegEx range.
*/
if (start > end)
{
System.
out.
println(printIndent
+ "Return as start value is greater than end.");
System.
out.
println(printIndent
+ "Exit method " + "getRegexPairsRecursion." + " Level [" + recursionLevel
+ "]."); return pairs;
}
/*
* Calculate first number ending with 0, which is greater than the start value.
* This will tell us whether or not start and end values differ only at last digit.
*/
int firstEndingWith0 = 10*((start+9)/10);
System.
out.
println(printIndent
+ "First number ending with 0 which is greater than start number [" + start
+ "] is: ["+ firstEndingWith0
+"]");
/*
* Start and end values differ only at the last digit.
*/
if (firstEndingWith0 > end) // not in range?
{
System.
out.
println(printIndent
+ "Start and end only differ at the last digit, no further processing needed.");
pairs.add(start);
pairs.add(end);
System.
out.
println(printIndent
+ "Exit method " + "getRegexPairsRecursion." + " Level [" + recursionLevel
+ "]."); return pairs;
}
/*
* start is not ending in 0.
*/
if (start < firstEndingWith0)
{
System.
out.
println(printIndent
+ "Start Range i.e. ["+ start
+"] does not end in 0. Add the numbers ["+start
+"] and [" + (firstEndingWith0
- 1) +"], to list."); pairs.add(start);
pairs.add(firstEndingWith0-1);
}
//Largest number ending with 9, which is smaller than the Range end.
int lastEndingWith9 = 10*(end/10)-1;
System.
out.
println(printIndent
+ "Last number in range, which ends with 9 is: ["+ lastEndingWith9
+"]");
System.
out.
println(printIndent
+ "New Working Range is ["+ firstEndingWith0
+ " - " + lastEndingWith9
+ "].");
System.
out.
println(printIndent
+ "Call Recursion with Range ["+ (firstEndingWith0
/10) + " - " + (lastEndingWith9
/10) + "].");
/*
* All RegEx for the range [firstEndingWith0,lastEndingWith9] end with [0-9],
* hence, remove the rightmost 0 from new working range start and remove the rightmost
* 9 from new working range end.
*/
List<Integer> pairsMiddle = getRegexPairsRecursion(firstEndingWith0/10, lastEndingWith9/10, recursionLevel+1);
System.
out.
println(printIndent
+ "Returned From Recursion ["+ firstEndingWith0
/10 + " - " + lastEndingWith9
/10 + "].");
System.
out.
println(printIndent
+ "Printing results from this call.");
for(int j = 0; j<pairsMiddle.size(); j++)
{
System.
out.
println(printIndent
+ "" + pairsMiddle.
get(j
)); }
/*
* Append digits to start and end of each pair. 0 will be appended to the low value of
* the pair and 9 will be appended to the high value of the pair.
* This is equivalent of multiplying low value by 10, and multiplying high value by 10
* and adding 9 to it.
*/
if(pairsMiddle.size() > 0)
{
System.
out.
println(printIndent
+ "Append digits to the generated pair(s)."); }
for (int i=0; i<pairsMiddle.size(); i+=2)
{
System.
out.
println(printIndent
+ pairsMiddle.
get(i
) + " --> " + (pairsMiddle.
get(i
) *10+0)); System.
out.
println(printIndent
+ pairsMiddle.
get(i
+1) + " --> " + (pairsMiddle.
get(i
+1)*10+9)); pairs.add(pairsMiddle.get(i) *10+0);
pairs.add(pairsMiddle.get(i+1)*10+9);
}
System.
out.
println(printIndent
+ "Printing the current list of pairs."); for(int j = 0; j<pairs.size(); j++)
{
System.
out.
println(printIndent
+ "" + pairs.
get(j
)); }
if (lastEndingWith9 < end) // end is not ending in 9
{
System.
out.
println(printIndent
+ "Range end [" + end
+ "] is greater than last number in current pair list [" + lastEndingWith9
+ "]"); System.
out.
println(printIndent
+ "Add ["+ (lastEndingWith9
+1) + "] and [" + end
+ "] to the list."); pairs.add(lastEndingWith9+1);
pairs.add(end);
}
System.
out.
println(printIndent
+ "Exit method " + "getRegexPairsRecursion." + " Level [" + recursionLevel
+ "]."); return pairs;
}
/**
* print the given list of integer pairs - used for debugging.
* @param list
*/
private void printPairList(List<Integer> list)
{
if (list.size() > 0)
{
System.
out.
println("Printing pair values of start and end as hyphen separated list."); System.
out.
println(String.
format("%d-%d", list.
get(0), list.
get(1))); int i = 2;
while (i < list.size())
{
System.
out.
println(String.
format("%d-%d", list.
get(i
), list.
get(i
+ 1))); i = i + 2;
}
}
}
/**
* return the regular expressions that match the ranges in the given
* list of integers. The list is in the form firstRangeStart, firstRangeEnd,
* secondRangeStart, secondRangeEnd, etc. Each regular expression is 0-left-padded,
* if necessary, to match strings of the given width.
* @param pairs
* @param minWidth
* @return
*/
private List<String> formatPairsToRegEx(List<Integer> pairs, int minWidth)
{
List<String> list = null;
list = new ArrayList<>();
for (Iterator<Integer> iterator = pairs.iterator(); iterator.hasNext();)
{
String start
= String.
format(numberWithWidth, iterator.
next()); String end
= String.
format(numberWithWidth, iterator.
next());
assert start.length() == end.length();
StringBuilder result = new StringBuilder();
for (int pos = 0; pos < start.length(); pos++)
{
if (start.charAt(pos) == end.charAt(pos))
{
result.append(start.charAt(pos));
} else
{
result.append('[').append(start.charAt(pos)).append('-')
.append(end.charAt(pos)).append(']');
}
}
list.add(result.toString());
}
return list;
}
}