In my application I need filter concept for numeric.So I need to generate dynamic regular expression format.For example if I gave input is like (attrN = number,operator="equal",value=459) and (attrN = number,operator="lessthan equal",value=57) and (attrN = number,operator="not equal",value=45) and (attrN = number,operator="greaterthan equal",value=1000).based on the above conditions need to develop dynamic regular expression.I tried lessthan equal condition but I didn't get union and subtraction also greater than equal conditions.I need the logic or algorithm.
public class NumericRangeRegex {
public String baseRange(String num, boolean up, boolean leading1) {
char c = num.charAt(0);
char low = up ? c : leading1 ? '1' : '0';
char high = up ? '9' : c;
if (num.length() == 1)
return charClass(low, high);
String re = c + "(" + baseRange(num.substring(1), up, false) + ")";
if (up) low++; else high--;
if (low <= high)
re += "|" + charClass(low, high) + nDigits(num.length() - 1);
return re;
}
private String charClass(char b, char e) {
return String.format(b==e ? "%c" : e-b>1 ? "[%c-%c]" : "[%c%c]", b, e);
}
private String nDigits(int n) {
return nDigits(n, n);
}
private String nDigits(int n, int m) {
return "[0-9]" + String.format(n==m ? n==1 ? "":"{%d}":"{%d,%d}", n, m);
}
private String eqLengths(String from, String to) {
char fc = from.charAt(0), tc = to.charAt(0);
if (from.length() == 1 && to.length() == 1)
return charClass(fc, tc);
if (fc == tc)
return fc + "("+rangeRegex(from.substring(1), to.substring(1))+")";
String re = fc + "(" + baseRange(from.substring(1), true, false) + ")|"
+ tc + "(" + baseRange(to.substring(1), false, false) + ")";
if (++fc <= --tc)
re += "|" + charClass(fc, tc) + nDigits(from.length() - 1);
return re;
}
private String nonEqLengths(String from, String to) {
String re = baseRange(from,true,false) + "|" + baseRange(to,false,true);
if (to.length() - from.length() > 1)
re += "|[1-9]" + nDigits(from.length(), to.length() - 2);
return re;
}
public String run(int n, int m) {
return "\\b0*?("+ rangeRegex("" + n, "" + m) +")\\b";
}
public String rangeRegex(String n, String m) {
return n.length() == m.length() ? eqLengths(n, m) : nonEqLengths(n, m);
}
}
Use a simple interface for this
public interface Check {
boolean isValidFor(int value);
}
Then implement different classes for different kind of checks like
public class isEqualTo implements Check {
private int valueToTestAgainst;
public isEqualTo(int test) {
valueToTestAgainst = test;
}
public boolean isValidFor(int value) {
return valueToTestAgainst == value;
}
}
public class isGreatherThan implements Check {
private int valueToTestAgainst;
public isGreatherThan(int test) {
valueToTestAgainst = test;
}
public boolean isValidFor(int value) {
return valueToTestAgainst > value;
}
}
And then have a class that parses the given input and creates a list of Check objects. Maybe create an abstract class to hold the check value (valueToTestAgainst) and/or make the implementation generic to support other types like double.
Based on conditions Ill try for union and subtraction is `^(?!250)0*?([0-9]|2(5([0-5])|[0-4][0-9])|1[0-9]{2}|[1-9][0-9]|2000)$. In this we are matching 1 to 255 range and 2000 numeric number(union) and for negate 250(subtraction).It's working fine.
Related
I want to compute dragon curve till n = 10 in java with L system using recursion. For example,
Replace all F characters with F-H
Replace all H characters with F+H
dragon(0) = F-H (this is the input)
dragon(1) = F-H-F+H
dragon(2) = F-H-F+H-F-H+F+H
...
dragon(10) = ?
How can I accomplish the same in java using recursion? I'm only interested in knowing the recursive approach.
In recursive approach such "replace" problem statements usually can be implemented as recursive calls.
So let's create two functions - F() and H() each of them will return "F" or "H" when desired curve depth is reached, or F(...) + "-" + H(...) or F(...) + "+" + H(...) if further expansion is needed.
private String F(int depth) {
if (depth == 0) {
return "F";
} else {
return F(depth - 1) + "-" + H(depth - 1);
}
}
private String H(int depth) {
if (depth == 0) {
return "H";
} else {
return F(depth - 1) + "+" + H(depth - 1);
}
}
public String dragon(int depth) {
return F(depth + 1);
}
Try it online!
This is a probable answer of my question in stack overflow.Integer to word conversion
At first I have started with dictionary. Then I came to know it is obsolete. So now I use Map instead of dictionary. My code is work well for number till Millions. But the approach I take here is a naive approach. The main problem of this code is
First: Huge numbers of variable use
2nd: Redundant code block as per program requirement
3rd: Multiple if else statement
I am thinking about this problems
Solution for 2nd problem: using user define function or macros to eliminate redundant code block
Solution for 3rd problem: Using switch case
My code:
public class IntegerEnglish {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
System.out.println("Enter the integer");
int input_number=in.nextInt();
Map<Integer,String> numbers_converter = new HashMap<Integer,String>();
Map<Integer,String> number_place = new HashMap<Integer,String>();
Map<Integer,String> number_2nd = new HashMap<Integer,String>();
numbers_converter.put(0,"Zero");
numbers_converter.put(1,"One");
numbers_converter.put(2,"Two");
numbers_converter.put(3,"Three");
numbers_converter.put(4,"Four");
numbers_converter.put(5,"Five");
numbers_converter.put(6,"Six");
numbers_converter.put(7,"Seven");
numbers_converter.put(8,"Eight");
numbers_converter.put(9,"Nine");
numbers_converter.put(10,"Ten");
numbers_converter.put(11,"Eleven");
numbers_converter.put(12,"Twelve");
numbers_converter.put(13,"Thirteen");
numbers_converter.put(14,"Fourteen ");
numbers_converter.put(15,"Fifteen");
numbers_converter.put(16,"Sixteen");
numbers_converter.put(17,"Seventeen");
numbers_converter.put(18,"Eighteen");
numbers_converter.put(19,"Nineteen");
number_place.put(3,"Hundred");
number_place.put(4,"Thousand");
number_place.put(7,"Million");
number_place.put(11,"Billion");
number_2nd.put(2,"Twenty");
number_2nd.put(3,"Thirty");
number_2nd.put(4,"Forty");
number_2nd.put(5,"Fifty");
number_2nd.put(6,"Sixty");
number_2nd.put(7,"Seventy");
number_2nd.put(8,"Eighty");
number_2nd.put(9,"Ninty");
if(input_number== 0){
System.out.println("zero");
}
else if(input_number>0 && input_number<19){
System.out.println(numbers_converter.get(input_number));
}
else if(input_number>19 && input_number<100){
int rem=input_number%10;
input_number=input_number/10;
System.out.print(number_2nd.get(input_number));
System.out.print(numbers_converter.get(rem));
}
else if(input_number==100){
System.out.println(number_place.get(3));
}
else if(input_number>100 && input_number<1000){
int reminder=input_number%100;
int r1=reminder%10;
int q1=reminder/10;
int quot=input_number/100;
System.out.print(numbers_converter.get(quot) + "hundred");
if(reminder>0 && reminder<20){
System.out.print(numbers_converter.get(reminder));
}
else{
System.out.println(number_2nd.get(q1) + numbers_converter.get(r1));
}
}
else if(input_number==1000){
System.out.println(number_place.get(4));
}
else if(input_number>1000 && input_number<10000){
int rem=input_number%100;
int rem_two=rem%10;
int quotient =rem/10;
input_number=input_number/100;
int thousand=input_number/10;
int hundred = input_number%10;
System.out.print(numbers_converter.get(thousand) + "thousand" + numbers_converter.get(hundred)+ " hundred");
if(rem >0 && rem<20){
System.out.print(numbers_converter.get(rem));
}
else if(rem >19 && rem <100){
System.out.print(number_2nd.get(quotient) + numbers_converter.get(rem_two));
}
}
else if(input_number>10000 && input_number<1000000000){
//Say number 418,229,356
int third_part=input_number%1000;//hold 356
input_number=input_number/1000;//hold 418,229
int sec_part=input_number%1000;//hold 229
input_number=input_number/1000;// hold 418
int rem_m=third_part%100;//hold 56
int rem_m1=rem_m%10;//hold 6
int rem_q=rem_m/10;// hold 5
int q_m=third_part/100;// hold 3
int sec_part_rem=sec_part%100;// hold 29
int sec_part_rem1=sec_part_rem%10;//9
int sec_part_q=sec_part_rem/10;//hold 2
int sec_q=sec_part/100;// hold 2
int input_q=input_number/100;// hold 4
int input_rem=input_number%100;//hold 18
int input_q_q=input_rem/10;//hold 1
int input_rem1=input_rem%10;// hold 8
System.out.print(numbers_converter.get(input_q) + " hundred ");
if(input_rem>0 && input_rem<20){
System.out.print(numbers_converter.get(input_rem)+ " Million ");
}
else{
System.out.print(number_2nd.get(input_q_q) + " " + numbers_converter.get(input_rem1) + " Million ");
}
System.out.print(numbers_converter.get(sec_q) + " hundred ");
if(sec_part_rem >0 && sec_part_rem<20){
System.out.println(numbers_converter.get(sec_part_rem) + " thousand ");
}
else{
System.out.print(number_2nd.get(sec_part_q) + " " + numbers_converter.get(sec_part_rem1) + " thousand ");
}
System.out.print(numbers_converter.get(q_m) + " hundred ");
if(rem_m>0 && rem_m<20){
System.out.print(numbers_converter.get(rem_m));
}
else{
System.out.print(number_2nd.get(rem_q) + " " + numbers_converter.get(rem_m1));
}
}
}
}
Redundant Code Blocks
int rem=input_number%100;
int rem_two=rem%10;
int quotient =rem/10;
input_number=input_number/100;
int thousand=input_number/10;
int hundred = input_number%10;
This type of code block used almost every where. Taking a number divide it with 100 or 1000 to find out the hundred position then then divide it with 10 to find out the tenth position of the number. Finally using %(modular division) to find out the ones position.
How could I include user define function and switch case to minimize the code block.
Instead of storing the results in variables, use a method call:
int remainder100(int aNumber) {
return aNumber % 100;
}
int remainder10(int aNumber) {
return aNumber % 10;
}
...etc.
System.out.println(numbers_converter.get(remainder100(input_number)));
About 3rd problem: I wouldn't use switch ... case, too many cases.
Instead, take advantage that numbering repeats itself every 3 digits. That means the pattern for thousands and millions is the same (and billions, trillions, etc).
To do that, use a loop like this:
ArrayList<String> partialResult = new ArrayList<String>();
int powersOf1000 = 0;
for (int kiloCounter = input_number; kiloCounter > 0; kiloCounter /= 1000) {
partialResult.add(getThousandsMilionsBillionsEtc(powersOf1000++);
partialResult.add(convertThreeDigits(kiloCounter % 1000));
}
Then you can print out the contents of partialResult in reverse order to get the final number.
I'd suggest you break your single main method down into a couple of classes. And if you haven't already create a few unit tests to allow you to easily test / refactor things. You'll find it quicker than starting the app and reading from stdin.
You'll find it easier to deal with the number as a string. Rather than dividing by 10 all the time you just take the last character of the string. You could have a class that does that bit for you, and a separate one that does the convert.
Here's what I came up with, but I'm sure it can be improved. It has a PoppableNumber class which allows the last character of the initial number to be easily retrieved. And the NumberToString class which has a static convert method to perform the conversion.
An example of a test would be
#Test
public void Convert102356Test() {
assertEquals("one hundred and two thousand three hundred and fifty six", NumberToString.convert(102356));
}
And here's the NumberToString class :
import java.util.HashMap;
import java.util.Map;
public class NumberToString {
// billion is enough for an int, obviously need more for long
private static String[] power3 = new String[] {"", "thousand", "million", "billion"};
private static Map<String,String> numbers_below_twenty = new HashMap<String,String>();
private static Map<String,String> number_tens = new HashMap<String,String>();
static {
numbers_below_twenty.put("0","");
numbers_below_twenty.put("1","one");
numbers_below_twenty.put("2","two");
numbers_below_twenty.put("3","three");
numbers_below_twenty.put("4","four");
numbers_below_twenty.put("5","five");
numbers_below_twenty.put("6","six");
numbers_below_twenty.put("7","seven");
numbers_below_twenty.put("8","eight");
numbers_below_twenty.put("9","nine");
numbers_below_twenty.put("10","ten");
numbers_below_twenty.put("11","eleven");
numbers_below_twenty.put("12","twelve");
numbers_below_twenty.put("13","thirteen");
numbers_below_twenty.put("14","fourteen ");
numbers_below_twenty.put("15","fifteen");
numbers_below_twenty.put("16","sixteen");
numbers_below_twenty.put("17","seventeen");
numbers_below_twenty.put("18","eighteen");
numbers_below_twenty.put("19","nineteen");
number_tens.put(null,"");
number_tens.put("","");
number_tens.put("0","");
number_tens.put("2","twenty");
number_tens.put("3","thirty");
number_tens.put("4","forty");
number_tens.put("5","fifty");
number_tens.put("6","sixty");
number_tens.put("7","seventy");
number_tens.put("8","eighty");
number_tens.put("9","ninty");
}
public static String convert(int value) {
if (value == 0) {
return "zero";
}
PoppableNumber number = new PoppableNumber(value);
String result = "";
int power3Count = 0;
while (number.hasMore()) {
String nextPart = convertUnitTenHundred(number.pop(), number.pop(), number.pop());
nextPart = join(nextPart, " ", power3[power3Count++], true);
result = join(nextPart, " ", result);
}
if (number.isNegative()) {
result = join("minus", " ", result);
}
return result;
}
public static String convertUnitTenHundred(String units, String tens, String hundreds) {
String tens_and_units_part = "";
if (numbers_below_twenty.containsKey(tens+units)) {
tens_and_units_part = numbers_below_twenty.get(tens+units);
}
else {
tens_and_units_part = join(number_tens.get(tens), " ", numbers_below_twenty.get(units));
}
String hundred_part = join(numbers_below_twenty.get(hundreds), " ", "hundred", true);
return join(hundred_part, " and ", tens_and_units_part);
}
public static String join(String part1, String sep, String part2) {
return join(part1, sep, part2, false);
}
public static String join(String part1, String sep, String part2, boolean part1Required) {
if (part1 == null || part1.length() == 0) {
return (part1Required) ? "" : part2;
}
if (part2.length() == 0) {
return part1;
}
return part1 + sep + part2;
}
/**
*
* Convert an int to a string, and allow the last character to be taken off the string using pop() method.
*
* e.g.
* 1432
* Will give 2, then 3, then 4, and finally 1 on subsequent calls to pop().
*
* If there is nothing left, pop() will just return an empty string.
*
*/
static class PoppableNumber {
private int original;
private String number;
private int start;
private int next;
PoppableNumber(int value) {
this.original = value;
this.number = String.valueOf(value);
this.next = number.length();
this.start = (value < 0) ? 1 : 0; // allow for minus sign.
}
boolean isNegative() {
return (original < 0);
}
boolean hasMore() {
return (next > start);
}
String pop() {
return hasMore() ? number.substring(--next, next+1) : "";
}
}
}
Im working on a school project where I have to implement recursion with arrays and I have done everything but im getting a null error when I am running it. The error points to the Recursion class on Line:
result += packetList[n].idNumber + " " + packetList[n].weight + " " + packetList[n].Destination;
I tried tracing the recursion method to see if it would actually make sense and its looks solid but i'm still getting a null error.
Recursion Class:
import java.io.*;
public class Recursion
{
public String toString(Packet[] packetList, int n)
{
String result = "";
if (n < 0)
{
return result;
}
result += packetList[n].idNumber + " " + packetList[n].weight + " " + packetList[n].Destination; // Uncomment if you want the values from last-to-first (last index to 0 index)
result += toString(packetList, n-1);
//result += packetList[n].idNumber + " " + packetList[n].weight + " " + packetList[n].Destination; // Uncomment if you want the values from first-to-last (0 index to last index)
return result;
}
}
Packet Class
public class Packet
{
public int idNumber;
public double weight;
public String Destination;
public Packet(int id, double w, String D)
{
idNumber = id;
weight = w;
Destination = D;
}
public boolean isHeavy()
{
if (weight > 10)
return true;
else
return false;
}
public String toString()
{
return idNumber + " " + weight + " " + Destination;
}
public double getWeight()
{
return weight;
}
public String getDestination()
{
return Destination;
}
}
Test Class
import java.io.*;
import java.util.*;
import java.util.Scanner;
public class TestPackages
{
public static void main (String[] args) throws IOException
{
Packet[] packetList = new Packet[100];
int idNumber;
double weight;
String Destination;
Scanner fileInput;
fileInput = new Scanner (new File("packetData.txt"));
int counter = 0;
while (fileInput.hasNextLine())
{
idNumber = fileInput.nextInt();
weight = fileInput.nextDouble();
Destination = fileInput.nextLine();
Packet myPacket = new Packet (idNumber, weight, Destination);
packetList[counter++] = myPacket;
}
Recursion recursion = new Recursion();
System.out.println(recursion.toString(packetList, packetList.length - 1));
recursion.displayHeavyPackages(packetList, packetList.length - 1);
recursion.displayPacketsToDest(packetList, packetList.length - 1, "CT");
recursion.countPacketsToDest(packetList, packetList.length - 1, "CT");
}
}
It looks like you are sending the length of the array to your toString() function, but it might not have the 100 elements initialized, try sending your ´counter´ instead :
System.out.println(recursion.toString(packetList, counter-1))
Please verify that packetData.txt has exactly 100 lines otherwise the program will throw a null pointer Exception.
The displayHeavyPackage method should validate if n==0 to avoid Array Index Out Bound exception
displayHeavyPackage
public void displayHeavyPackages(Packet[] packetList, int n) {
if (packetList[n].isHeavy() == true && n>0) {
System.out.println(packetList[n]); displayHeavyPackages(packetList, n-1);
} else if (packetList[n].isHeavy() == true && n==0){
System.out.println(packetList[n]);
}
}
My final suggestion is try to debug your code, it will help a lot to clarify the root cause of the exceptions.
This question already has an answer here:
What does "Incompatible types: void cannot be converted to ..." mean?
(1 answer)
Closed 3 years ago.
I need to write a Java program for a course I'm taking which looks for genes in a strand of DNA.The Issue I am having is that from the test method, I need to pass printAllgenes(a) to the void printAllgenes method. In the test method I've tried setting 'int a' to 'String a', but in either case an error when compiling explaining that void cannot be converted to int or String. I'm sure its obvious, but I'm very new to programming, so please pardon my ignorance! Thank you.
import java.io.*;
import edu.duke.*;
public class FindProtein {
public void test() {
String a = "atg aaa tab tag atg aaa tga aat ag";
int b = printAllgenes(a);
System.out.println("DNA string is " + a);
System.out.println("Gene found is " + b);
}
public void printAllgenes(String dna) {
int sp = 0; //start point
while (true) {
int start = dna.indexOf("atg,sp");
if (start == -1) {
break;
}
int stop = findStopIndex(dna, start + 3);
if (stop != dna.length()) {
System.out.println(dna.substring(start, stop + 3));
sp = stop + 3;
} else {
sp = sp + 3;
}
}
}
public int findStopIndex(String dna, int index) {
int tga = dna.indexOf("tga", index);
if (tga == -1 || (tga - index) % 3 != 0) {
tga = dna.length();
}
int taa = dna.indexOf("taa", index);
if (taa == -1 || (taa - index) % 3 != 0) {
taa = dna.length();
}
int tag = dna.indexOf("tag", index);
if (tag == -1 || (tga - index) % 3 != 0) {
tag = dna.length();
}
return Math.min(tga, Math.min(taa, tag));
}
}
Try to use just:
printAllgenes(a);
Because printAllgenes method doesn't have any type of return statement.
change return type void to int It will return your count whatever u want to return from printAllgenes(String dns) Method. You will get a int return which will initialize you variable b that is being displayed on Console.
public int printAllgenes(String dna){
int sp = 0; //start point
while (true){
int start = dna.indexOf("atg,sp");
if (start==-1){
break;
}
int stop = findStopIndex(dna,start+3);
if (stop!=dna.length()){
System.out.println(dna.substring(start,stop+3));
sp=stop+3;
}
else{
sp=sp+3;
}
}
return sp;
}
Now Your Test Method Implementation will work fine...
public void test(){
String a= "atg aaa tab tag atg aaa tga aat ag";
int b = printAllgenes(a);
System.out.println("DNA string is " +a);
System.out.println("Gene found is "+b);
}
Thank you..
I'm using a regular expression to validate a certain format in a string. This string will become a rule for a game.
Example: "DX 3" is OK according to the rule, but "DX 14" could be OK too... I know how to look at the string and find one or more "numbers", so the problem is that the regex will match 34 too, and this number is out of "range" for the rule...
Am I missing something about the regex to do this? Or is this not possible at all?
Unfortunately there's no easy way to define ranges in regex. If you are to use the range 1-23 you'll end up with a regex like this:
([1-9]|1[0-9]|2[0-3])
Explanation:
Either the value is 1-9
or the value starts with 1 and is followed with a 0-9
or the value starts with 2 and is followed with a 0-3
It is not that short, and not flexible.
If you search for 1 to 19, you can search for "DX 1?[0-9]", for example, but if it doesn't end at a number boundary, it get's ugly pretty soon, and changing the rules is not flexible.
Splitting the String at the blank, and then using x > 0 and x < 24 is better to understand and more flexible.
You can use following format for writing a regular expression solving your problem.
Suppose your range is 0-15.
"^DX [0-9]|1[0-5]$"
You can even make it dynamic depending on your range by appending strings.
package dev.dump;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Collections;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA. User: User Date: 28.09.2007 Time: 9:46:47 To change this template use
* File | Settings | File Templates.
*/
class NumberDiapasone2RegExp {
private static final String invalidArgumentEmpty="Invalid argument \"{0}\" was found! {1}";
private static final Pattern pattern=Pattern.compile("^(\\d+)-(\\d+)?$");
private String src;
private String result="";
private Long left;
private Long right;
private boolean transform09ToD;
public NumberDiapasone2RegExp(final String src) {
this(src, false);
}
public NumberDiapasone2RegExp(final String src, final boolean transform09ToD) {
this.transform09ToD=transform09ToD;
if (src==null || src.trim().length()==0)
throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty,
src,
"It cannot be empty."));
if (src.indexOf("-")<0)
throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty,
src,
"It is supposed to have \"-\"."));
if (src.indexOf("-")!=src.lastIndexOf("-"))
throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty,
src,
"It is supposed to have only one \"-\"."));
Matcher syntaxChecker=pattern.matcher(src);
if (!syntaxChecker.find()){
throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty,
src,
"It is supposed to be in format \"##-##\"."));
}
this.src=src;
parseAndCheck();
String theSameDigits="";
//the same digit goes towards result
if (left.toString().length()==right.toString().length()){
for (int i=0; i<left.toString().length(); i++){
if (i<right.toString().length() &&
left.toString().charAt(i)==right.toString().charAt(i)){
theSameDigits+=left.toString().charAt(i);
}
}
if (theSameDigits.length()>0){
this.src=this.src.replaceFirst(Pattern.quote(theSameDigits),"");
this.src=this.src.replaceFirst(Pattern.quote("-"+theSameDigits),"-");
parseAndCheck();
}
}
result=glueParts(compact(transform09ToD, toParts()));
Matcher m=secondCompact.matcher(result);
while (m.find()){
result=m.group(1).replace("(","").replace(")","")+"["+m.group(2).replaceAll("[\\[\\]]","")+m.group(3).replaceAll("[\\[\\]]","")+"][0-9]";
m.reset(result);
}
//compact squares again
StringBuffer sb=new StringBuffer();
Pattern squresP=Pattern.compile("(\\[(\\d|-)+\\])");
m=squresP.matcher(result);
while (m.find()) {
m.appendReplacement(sb, Matcher.quoteReplacement(compactSquares(m.group(1))));
}
m.appendTail(sb);
result=sb.toString();
result=result.replaceAll("\\[(\\d)-\\1\\]","$1");
result=result.replaceAll("\\[(\\d)\\]","$1");
result=result.replace("{1}","").replace("{0,1}","?");
if (result.indexOf("|")>=0) result=theSameDigits+"("+result+")";
else result=theSameDigits+result;
if (result.startsWith("(") && result.endsWith(")")) result=result.substring(1, result.length()-1);
}
private static Pattern secondCompact=Pattern.compile("(.*)(\\[\\d-?\\d\\]|\\d)\\[0-9\\]\\|(\\[\\d-?\\d\\]|\\d)\\[0-9\\]");
static List<String> compact(boolean transform09ToD, String... parts) {
Set<String> unique=new HashSet<String>();
List<String> result=new ArrayList<String>();
for (String part : parts){
if (part==null || part.length()==0) continue;
part=compactSquares(part);
part=part.replaceAll("\\[(\\d)\\]","$1");
if (part.indexOf("[0-9]")>=0){
if (transform09ToD) part=part.replace("[0-9]","\\d");
}
//[0-3][0-9]|4[0-9]=>[0-34][0-9]
//[023][0-9]|4[0-9]=>[0234][0-9]
//[02345789]=>[02-57-9]
Matcher m=secondCompact.matcher(part);
if (m.find()){
part=m.group(1).replace("(","").replace(")","")+"["+m.group(2).replaceAll("[\\[\\]]","")+m.group(3).replaceAll("[\\[\\]]","")+"][0-9]";
}
part=part.replaceAll("\\[(\\d)-\\1\\]","$1");
if (unique.add(part)) result.add(part);
}
return result;
}
static String compactSquares(String src){
boolean inSquares=false;
if (src.startsWith("[") && src.endsWith("]")){
inSquares=true;
src=src.substring(1,src.length()-1);
}
StringBuffer sb=new StringBuffer();
if (!src.contains("-")) {
List<Integer> digits=new ArrayList<Integer>();
for (int i=0; i<src.length();i++){
digits.add(Integer.parseInt(""+src.charAt(i)));
}
Collections.sort(digits);
for (Integer s : digits){
sb.append(s);
}
src=sb.toString();
sb.setLength(0);
}
int firstChar = -2;
int lastChar = -2;
int currentChar;
for (int i=0; i<src.length(); i++) {
currentChar=src.charAt(i);
if (currentChar == lastChar + 1) {
lastChar = currentChar;
continue;
}
if (currentChar == '-' && i+1 < src.length()) {
lastChar = src.charAt(i + 1) - 1;
continue;
}
flush(sb, firstChar, lastChar);
firstChar = currentChar;
lastChar = currentChar;
}
flush(sb, firstChar, lastChar);
return (inSquares?"[":"")+sb.toString()+(inSquares?"]":"");
}
private static void flush(StringBuffer sb, int firstChar, int lastChar) {
if (lastChar<=0) return;
if (firstChar==lastChar) {
sb.append((char)firstChar);
return;
}
if (firstChar+1==lastChar){
sb.append((char)firstChar);
sb.append((char)lastChar);
return;
}
sb.append((char)firstChar);
sb.append('-');
sb.append((char)lastChar);
}
static String glueParts(List<String> parts) {
if (parts==null || parts.isEmpty()) return "";
if (parts.size()==1) return parts.get(0);
StringBuilder result=new StringBuilder(128);
for (String part : parts){
result.append(part);
result.append("|");
}
result.deleteCharAt(result.length()-1);
return result.toString();
}
private String[] toParts() {
List<String> result=new ArrayList<String>();
if (getNumberOfDigits(left)>2 || getNumberOfDigits(right)>2) {
result.add(startPart(left));
}
long leftPart=left;
long rightPart=right;
if (!String.valueOf(left).matches("10*")) leftPart=toPower(left);
if (!String.valueOf(right).matches("10*")) rightPart=toPower(right)/10;
if (rightPart/leftPart>=10) {
result.add(speedUpPart(left, right));
}
//for 1-2 digit process
if (getNumberOfDigits(left)==1 && getNumberOfDigits(right)==1){
result.add("["+left+"-"+right+"]");
}
else if (getNumberOfDigits(left)==1 && getNumberOfDigits(right)==2){
if (0==Integer.parseInt(getMajorDigit(right))) {
result.add(getMajorDigit(left)+
"["+
getMajorDigit(getNumberWithoutMajorDigit(left))+
"-"+
getMajorDigit(getNumberWithoutMajorDigit(right))+
"]");
}
else if (1==Integer.parseInt(getMajorDigit(right))) {
result.add("["+
getMajorDigit(getNumberWithoutMajorDigit(left))+
"-9]");
result.add(getMajorDigit(right)+
"[0-"+
getMajorDigit(getNumberWithoutMajorDigit(right))+
"]");
}
else if (2<=Integer.parseInt(getMajorDigit(right))) {
result.add("["+
getMajorDigit(left)+
"-9]");
result.add("[1-"+
(Integer.parseInt(getMajorDigit(right))-1)+
"][0-9]");
result.add(getMajorDigit(right)+
"[0-"+
getMajorDigit(getNumberWithoutMajorDigit(right))+
"]");
}
else throw new IllegalStateException();
}
else if (getNumberOfDigits(left)==2 && getNumberOfDigits(right)==2){
if (Integer.parseInt(getMajorDigit(left))==Integer.parseInt(getMajorDigit(right))) {
result.add(getMajorDigit(left)+
"["+
getMajorDigit(getNumberWithoutMajorDigit(left))+
"-"+
getMajorDigit(getNumberWithoutMajorDigit(right))+
"]");
}
else if (Integer.parseInt(getMajorDigit(left))+1==Integer.parseInt(getMajorDigit(right))) {
result.add(getMajorDigit(left)+
"["+
getMajorDigit(getNumberWithoutMajorDigit(left))+
"-9]");
result.add(getMajorDigit(right)+
"[0-"+
getMajorDigit(getNumberWithoutMajorDigit(right))+
"]");
}
else if (Integer.parseInt(getMajorDigit(left))+2<=Integer.parseInt(getMajorDigit(right))) {
result.add(getMajorDigit(left)+
"["+
getMajorDigit(getNumberWithoutMajorDigit(left))+
"-9]");
result.add("["+(Integer.parseInt(getMajorDigit(left))+1)+
"-"+(Integer.parseInt(getMajorDigit(right))-1)+
"][0-9]");
result.add(getMajorDigit(right)+
"[0-"+
getMajorDigit(getNumberWithoutMajorDigit(right))+
"]");
}
else throw new IllegalStateException();
}
else result.add(staticPart(right));
result.add(breakPart(right));
return result.toArray(new String[0]);
}
static String breakPart(final Long number) {
if (getNumberOfDigits(number)<=2) {
return "";
}
StringBuilder result=new StringBuilder(256);
StringBuilder staticSection=new StringBuilder(32);
staticSection.append(getMajorDigit(number));
for (int i=1; i<getNumberOfDigits(number)-1; i++){
if (i!=1) result.append("|");
result.append(staticSection.toString());
staticSection.append(String.valueOf(number).charAt(i));
final long nextDigit=Long.parseLong(""+String.valueOf(number).charAt(i))-1;
if (nextDigit<0) {
result.setLength(0);
result.append("|");
continue;
}
if (nextDigit==0) result.append("0");
else if (nextDigit==1) result.append("[01]");
else result.append("[0-"+(nextDigit)+"]");
final int numberOfRepeats=(getNumberOfDigits(number)-i-1);
if (numberOfRepeats==1) result.append("[0-9]");
else result.append("[0-9]{"+numberOfRepeats+"}");
}
//остаток - 2 последние цифры числа
if (result.length()>0) {
result.append("|");
result.append(staticSection.toString());
//последнюю цифру от 0 до нее
result.append("[0-"+Long.parseLong(number.toString().replaceFirst("\\d+(\\d)","$1"))+"]");
}
if (result.length()>0) return result.toString().replace("||","|").replaceAll("^\\|","");
return "";
}
static String staticPart(final Long number) {
final long majorDigitMinus1=(Long.parseLong(getMajorDigit(number))-1);
if (majorDigitMinus1<=0) return "";
if (majorDigitMinus1==2) return "[1"+majorDigitMinus1+"][0-9]{"+(getNumberOfDigits(number)-1)+"}";
else if (majorDigitMinus1==1) return "1[0-9]{"+(getNumberOfDigits(number)-1)+"}";
return "[1-"+majorDigitMinus1+"][0-9]{"+(getNumberOfDigits(number)-1)+"}";
}
/**
* [1-9][0-9]{<X-1>,<Y-1>}, where X-number of digits of less number, Y-number of digits of greater number
*/
static String speedUpPart(Long left, Long right) {
//найти ближайшее до 0 то есть для 23 найти 100 для 777 найти 1000
//округленные до ближайшего 0
if (!String.valueOf(left).matches("10*")) left=toPower(left);
if (!String.valueOf(right).matches("10*")) right=toPower(right)/10;
final int leftPartRepeat=getNumberOfDigits(left)+(String.valueOf(left).matches("10*")?0:1)-1;
final int rightPartRepeat=getNumberOfDigits(right)+(String.valueOf(right).matches("10*")?0:1)-2;
if (getNumberOfDigits(left)==1 && getNumberOfDigits(right)==2)
return "[1-9]";
else if (leftPartRepeat>=rightPartRepeat)
return "[1-9][0-9]{"+rightPartRepeat+"}";
else
return "[1-9][0-9]{"+leftPartRepeat+","+rightPartRepeat+"}";
}
private static long toPower(final Long number) {
final double dValue=Math.pow(10, getNumberOfDigits(number));
final String value=String.format(Locale.US,"%24.0f",dValue);
return Long.parseLong(value.replaceFirst("\\s*(\\d+)(\\D\\d+)?","$1"));
}
private static int getNumberOfDigits(long number){
return (String.valueOf(number).length());
}
private static String getMajorDigit(long number){
return (String.valueOf(number).substring(0,1));
}
private static long getNumberWithoutMajorDigit(long number){
return Long.parseLong(String.valueOf(number).replaceFirst("\\d(\\d+)","$1"));
}
/**
* f(<n>>2)=<major digit>(f(<n-1>)|[<major digit+1>-9][0-9]{<n-1>})
*/
static String startPart(long number) {
int i=getNumberOfDigits(number);
if (i==1) {
if (number==9) return "9";
else if (number==8) return "[89]";
return "["+number+"-9]";
}
final long majorPlusOne=Long.parseLong(getMajorDigit(number))+1;
final int numberOfDigitsMinusOne=getNumberOfDigits(number)-1;
String result = (majorPlusOne < 10 ? "(" : "");
result+=getMajorDigit(number);
result+=startPart(getNumberWithoutMajorDigit(number));
result+=result.indexOf("|")<0 && majorPlusOne<10 && majorPlusOne!=numberOfDigitsMinusOne && numberOfDigitsMinusOne>1?"{"+numberOfDigitsMinusOne+"}":"";
result+=(majorPlusOne < 10
? "|[" + majorPlusOne + "-9][0-9]"+(numberOfDigitsMinusOne > 1 ? "{" + numberOfDigitsMinusOne + "}" : "")
: "");
result+=(majorPlusOne < 10 ? ")" : "");
return result;
}
private void parseAndCheck() {
Matcher matcher=pattern.matcher(src);
matcher.find();
try{
left=Long.parseLong(matcher.group(1));
right=Long.parseLong(matcher.group(2));
}
catch(Exception ex){
left=right+1;
}
if (left>right){
throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty,
src,
"Left part must be less than right one."));
}
}
public String getPattern() {
return result;
}
public static void main(String[] args) {
System.err.println(new NumberDiapasone2RegExp(args[0]).getPattern());
}
}
I was also trying to find a range of valid range for minutes
[0-60] worked for me.
I am using jdk 1.8 though