• Source
    1. /* package whatever; // don't place package name! */
    2.  
    3. import java.util.*;
    4. import java.lang.*;
    5. import java.io.*;
    6. import java.util.ArrayList;
    7. import java.util.Iterator;
    8. import java.util.List;
    9.  
    10.  
    11. /*
    12. Name of the class has to be "Main" only if the class is public.
    13. Code has been taken from the following three sources and bundled
    14. together for a full solution.
    15. Algorithm - https://stackoverflow.com/a/33539325/6385674
    16. Overall Code - https://stackoverflow.com/a/33554746/6385674
    17. Recursion Method - https://stackoverflow.com/a/33597252/6385674
    18. */
    19. class Ideone
    20. {
    21. protected String[] regexArray = null;
    22. protected List<String> regexList = null;
    23.  
    24. public static void main (String[] args) throws java.lang.Exception
    25. {
    26. Ideone ideone = new Ideone();
    27. ideone.generateRegEx("287", "2678905");
    28. for (String s: ideone.regexArray) { System.out.println(s); }
    29. }
    30. public Ideone()
    31. {
    32. regexList = new ArrayList<String>();
    33. }
    34. /**
    35. * Return a list of regular expressions that match the numbers
    36. * that fall within the range of the given numbers, inclusive.
    37. * Assumes the given strings are numbers of the the same length,
    38. * and 0-left-pads the resulting expressions, if necessary, to the
    39. * same length.
    40. * @param begStr
    41. * @param endStr
    42. */
    43. public void generateRegEx(String begStr, String endStr)
    44. {
    45.  
    46. //Log Input Data.
    47. System.out.println("Starting getRegex Method with String input.");
    48. System.out.println("Input Data is: ");
    49. System.out.println("Range Start : [" + begStr + "]");
    50. System.out.println("Range End : [" + endStr + "]");
    51.  
    52. //Get integer range values.
    53. System.out.println("Converting input string range values to integer values.");
    54.  
    55. int beg = Integer.parseInt(begStr);
    56. int end = Integer.parseInt(endStr);
    57.  
    58. System.out.println("Successfully converted input string range values to integer values.");
    59.  
    60. //Print integer values
    61. System.out.println("Range Start (Int) : [" + beg + "]");
    62. System.out.println("Range End (Int) : [" + end + "]");
    63.  
    64. //call common method to generate RegEx Pairs.
    65. generateRegExCommon(beg,end,begStr.length());
    66.  
    67. }
    68.  
    69. /**
    70. * Return a list of regular expressions that match the numbers
    71. * that fall within the range of the given numbers, inclusive.
    72. * @param beg
    73. * @param end
    74. *
    75. **/
    76. public void generateRegEx(int beg, int end)
    77. {
    78.  
    79. //Log Input Data.
    80. System.out.println("Starting getRegex Method with integer input.");
    81. System.out.println("Input Data is: ");
    82. System.out.println("Range Start : [" + beg + "]");
    83. System.out.println("Range End : [" + end + "]");
    84.  
    85. //call common method to generate RegEx Pairs.
    86. generateRegExCommon(beg,end,0);
    87. }
    88.  
    89. private void generateRegExCommon(int start, int end, int stringLength)
    90. {
    91. //call method to generate RegEx Pairs.
    92. System.out.println("Calling method to generate RegEx pairs for the input.");
    93.  
    94. List<Integer> pairs = getRegexPairsRecursion(start, end, 1);
    95.  
    96. System.out.println("Returned from method with a List of RegEx pairs for the input.");
    97. System.out.println("Total RegEx Ranges: [" + pairs.size()/2 + "]");
    98.  
    99. System.out.println("Printing range values.");
    100. pairs.forEach(s-> System.out.println(s+""));
    101. System.out.println("Completed printing range values.");
    102.  
    103. printPairList(pairs);
    104.  
    105. //String length of the input is used to identify if any leading zeros need to be prepended to the RegEx pairs.
    106. System.out.println("String length of input is: [" + stringLength + "]");
    107.  
    108. System.out.println("Calling method to convert range pairs to RegEx.");
    109. //regexList = toRegex(pairs, stringLength);
    110. regexList = formatPairsToRegEx(pairs, stringLength);
    111. System.out.println("Completed converting range pairs to RegEx.");
    112.  
    113. System.out.println("Printing RegEx list.");
    114. regexList.forEach(s-> System.out.println(s+""));
    115. System.out.println("Completed printing RegEx list.");
    116.  
    117. System.out.println("Converting RegEx list to an array.");
    118. regexArray = regexList.toArray(new String[regexList.size()]);
    119. System.out.println("Completed converting RegEx list to an array.");
    120.  
    121. System.out.println("Printing RegEx array.");
    122. regexList.forEach(s-> System.out.println(s+""));
    123. System.out.println("Completed printing RegEx array.");
    124. }
    125.  
    126. /**
    127. * return the list of integers that are the paired integers
    128. * used to generate the regular expressions for the given
    129. * range. Each pair of integers in the list -- 0,1, then 2,3,
    130. * etc., represents a range for which a single regular expression
    131. * is generated.
    132. * @param start
    133. * @param end
    134. * @return
    135. */
    136. private List<Integer> getRegexPairsRecursion(int start, int end, int recursionLevel)
    137. {
    138. List<Integer> pairs = null;
    139.  
    140. pairs = new ArrayList<>();
    141. String printIndent = "";
    142.  
    143. for (int i = 0; i <= recursionLevel - 1; i++)
    144. {
    145. printIndent += " ";
    146. }
    147.  
    148. System.out.println(printIndent + "Entering method " + "getRegexPairsRecursion." + " Level [" + recursionLevel + "].");
    149.  
    150. System.out.println(printIndent + "Start Range : [" + start + "]");
    151. System.out.println(printIndent + "End Range : [" + end + "]");
    152.  
    153. if(start == 0)
    154. {
    155. System.out.println(printIndent + "Range start value is 0. Add pair of zeros and set start range value to 1.");
    156. pairs.add(0);
    157. pairs.add(0);
    158. start = 1;
    159. }
    160.  
    161. /*If start is greater than end of the range, return the current values in pairs.
    162. * Apart from the special case when start value is 0, this will always be empty,
    163. *because if start is greater than end range value, it cannot be represented using
    164. *RegEx range.
    165. */
    166. if (start > end)
    167. {
    168. System.out.println(printIndent + "Return as start value is greater than end.");
    169.  
    170. System.out.println(printIndent + "Exit method " + "getRegexPairsRecursion." + " Level [" + recursionLevel + "].");
    171. return pairs;
    172. }
    173.  
    174. /*
    175. * Calculate first number ending with 0, which is greater than the start value.
    176. * This will tell us whether or not start and end values differ only at last digit.
    177. */
    178. int firstEndingWith0 = 10*((start+9)/10);
    179. System.out.println(printIndent + "First number ending with 0 which is greater than start number [" + start + "] is: ["+ firstEndingWith0 +"]");
    180.  
    181. /*
    182. * Start and end values differ only at the last digit.
    183. */
    184. if (firstEndingWith0 > end) // not in range?
    185. {
    186. System.out.println(printIndent + "Start and end only differ at the last digit, no further processing needed.");
    187.  
    188. pairs.add(start);
    189. pairs.add(end);
    190.  
    191. System.out.println(printIndent + "Exit method " + "getRegexPairsRecursion." + " Level [" + recursionLevel + "].");
    192. return pairs;
    193. }
    194.  
    195. /*
    196. * start is not ending in 0.
    197. */
    198. if (start < firstEndingWith0)
    199. {
    200. System.out.println(printIndent + "Start Range i.e. ["+ start +"] does not end in 0. Add the numbers ["+start+"] and [" + (firstEndingWith0 - 1) +"], to list.");
    201. pairs.add(start);
    202. pairs.add(firstEndingWith0-1);
    203. }
    204.  
    205. //Largest number ending with 9, which is smaller than the Range end.
    206. int lastEndingWith9 = 10*(end/10)-1;
    207. System.out.println(printIndent + "Last number in range, which ends with 9 is: ["+ lastEndingWith9 +"]");
    208.  
    209. System.out.println(printIndent + "New Working Range is ["+ firstEndingWith0 + " - " + lastEndingWith9 + "].");
    210.  
    211. System.out.println(printIndent + "Call Recursion with Range ["+ (firstEndingWith0/10) + " - " + (lastEndingWith9/10) + "].");
    212.  
    213. /*
    214. * All RegEx for the range [firstEndingWith0,lastEndingWith9] end with [0-9],
    215. * hence, remove the rightmost 0 from new working range start and remove the rightmost
    216. * 9 from new working range end.
    217. */
    218. List<Integer> pairsMiddle = getRegexPairsRecursion(firstEndingWith0/10, lastEndingWith9/10, recursionLevel+1);
    219.  
    220. System.out.println(printIndent + "Returned From Recursion ["+ firstEndingWith0/10 + " - " + lastEndingWith9/10 + "].");
    221.  
    222. System.out.println(printIndent + "Printing results from this call.");
    223.  
    224. for(int j = 0; j<pairsMiddle.size(); j++)
    225. {
    226. System.out.println(printIndent + "" + pairsMiddle.get(j));
    227. }
    228.  
    229. /*
    230. * Append digits to start and end of each pair. 0 will be appended to the low value of
    231. * the pair and 9 will be appended to the high value of the pair.
    232. * This is equivalent of multiplying low value by 10, and multiplying high value by 10
    233. * and adding 9 to it.
    234. */
    235.  
    236. if(pairsMiddle.size() > 0)
    237. {
    238. System.out.println(printIndent + "Append digits to the generated pair(s).");
    239. }
    240. for (int i=0; i<pairsMiddle.size(); i+=2)
    241. {
    242. System.out.println(printIndent + pairsMiddle.get(i) + " --> " + (pairsMiddle.get(i) *10+0));
    243. System.out.println(printIndent + pairsMiddle.get(i+1) + " --> " + (pairsMiddle.get(i+1)*10+9));
    244. pairs.add(pairsMiddle.get(i) *10+0);
    245. pairs.add(pairsMiddle.get(i+1)*10+9);
    246. }
    247.  
    248. System.out.println(printIndent + "Printing the current list of pairs.");
    249. for(int j = 0; j<pairs.size(); j++)
    250. {
    251. System.out.println(printIndent + "" + pairs.get(j));
    252. }
    253.  
    254. if (lastEndingWith9 < end) // end is not ending in 9
    255. {
    256. System.out.println(printIndent + "Range end [" + end + "] is greater than last number in current pair list [" + lastEndingWith9 + "]");
    257. System.out.println(printIndent + "Add ["+ (lastEndingWith9+1) + "] and [" + end + "] to the list.");
    258. pairs.add(lastEndingWith9+1);
    259. pairs.add(end);
    260. }
    261.  
    262. System.out.println(printIndent + "Exit method " + "getRegexPairsRecursion." + " Level [" + recursionLevel + "].");
    263. return pairs;
    264. }
    265.  
    266. /**
    267. * print the given list of integer pairs - used for debugging.
    268. * @param list
    269. */
    270. private void printPairList(List<Integer> list)
    271. {
    272. if (list.size() > 0)
    273. {
    274. System.out.println("Printing pair values of start and end as hyphen separated list.");
    275. System.out.println(String.format("%d-%d", list.get(0), list.get(1)));
    276. int i = 2;
    277. while (i < list.size())
    278. {
    279. System.out.println(String.format("%d-%d", list.get(i), list.get(i + 1)));
    280. i = i + 2;
    281. }
    282. }
    283. }
    284. /**
    285. * return the regular expressions that match the ranges in the given
    286. * list of integers. The list is in the form firstRangeStart, firstRangeEnd,
    287. * secondRangeStart, secondRangeEnd, etc. Each regular expression is 0-left-padded,
    288. * if necessary, to match strings of the given width.
    289. * @param pairs
    290. * @param minWidth
    291. * @return
    292. */
    293. private List<String> formatPairsToRegEx(List<Integer> pairs, int minWidth)
    294. {
    295. List<String> list = null;
    296. list = new ArrayList<>();
    297. String numberWithWidth = String.format("%%0%dd", minWidth);
    298. for (Iterator<Integer> iterator = pairs.iterator(); iterator.hasNext();)
    299. {
    300. String start = String.format(numberWithWidth, iterator.next());
    301. String end = String.format(numberWithWidth, iterator.next());
    302.  
    303. assert start.length() == end.length();
    304.  
    305. StringBuilder result = new StringBuilder();
    306.  
    307. for (int pos = 0; pos < start.length(); pos++)
    308. {
    309. if (start.charAt(pos) == end.charAt(pos))
    310. {
    311. result.append(start.charAt(pos));
    312. } else
    313. {
    314. result.append('[').append(start.charAt(pos)).append('-')
    315. .append(end.charAt(pos)).append(']');
    316. }
    317. }
    318.  
    319. list.add(result.toString());
    320. }
    321. return list;
    322. }
    323. }