Edit: Based on the hitEnd()
hint from maaartinus hitEnd()
hint from maaartinus
Edit: Based on the hitEnd()
hint from maaartinus
Edit: Based on the hitEnd()
hint from maaartinus
public List<List<SymbolChoice>> forceFitRegex(final String regex) {
return forceFitRegex(regex, false);
}
public List<List<SymbolChoice>> forceFitRegex(final String regex, boolean debug) {
Objects.requireNonNull(regex, "regex");
final List<Symbol> symbols = getSymbols();
SymbolChoice[][] options = new SymbolChoice[symbols.size()][];
int pos = 0;
int combinations = 1;
final SymbolChoice[] emptyChoice = new SymbolChoice[0];
for (Symbol symbol : getSymbols()) {
options[pos] = symbol.getSymbolChoices().toArray(emptyChoice);
combinations *= options[pos].length;
pos++;
}
Pattern pattern = Pattern.compile(regex);
int[] stack = new int[options.length];
int[] sbsize = new int[options.length + 1];
List<List<SymbolChoice>> listOfSymbolChoices = new ArrayList<List<SymbolChoice>>();
StringBuilder sb = new StringBuilder(stack.length);
int depth = 0;
int testcnt = 0;
while (depth >= 0) {
if (depthstack[depth] ==>= optionsoptions[depth].length) {
Matcher matcherstack[depth] = pattern.matcher(sb);0;
testcnt++;depth--;
if (matcher.matches()depth >= 0) {
// we havesb.setLength(sbsize[depth]);
a viable answer here, we can report it....
stack[depth]++;
List<SymbolChoice> match = new ArrayList<>(stack.length);}
} else {
for (int i = 0; i < stacksb.length; i++append(options[depth][stack[depth]].symbol.value) {;
Matcher matcher = matchpattern.addmatcher(options[i][stack[i]]sb);
}testcnt++;
boolean found = listOfSymbolChoicesmatcher.addmatches(match);
}
if (depth == options.length - 1) {
depth--;
if sb.setLength(sbsize[depth]found); {
stack[depth]++;
}// elsewe ifhave (stack[depth]a >=viable options[depth].length)answer {
here, we can report it....
stack[depth] = 0;
List<SymbolChoice> match = depth--new ArrayList<>(stack.length);
if for (depthint >=i 0= 0; i < stack.length; i++) {
sb match.setLengthadd(sbsize[depth]options[i][stack[i]]);
stack[depth]++;
}
}
} else { listOfSymbolChoices.add(match);
sb.append(options[depth][stack[depth]].symbol.value); }
Matcher matcher = pattern sb.matchersetLength(sbsbsize[depth]);
testcnt++; stack[depth]++;
} else if (matcher.find()found || matcher.hitEnd()) {
// we have a viable answer here, we can descend....
depth++;
sbsize[depth] = sb.length();
} else {
// nothing viable down here....
sb.setLength(sbsize[depth]);
stack[depth]++;
}
}
}
if (debug) {
System.out.println("Combinations: " + combinations + " actual tests " + testcnt);
}
return listOfSymbolChoices;
}
public List<List<SymbolChoice>> forceFitRegex(final String regex) {
return forceFitRegex(regex, false);
}
public List<List<SymbolChoice>> forceFitRegex(final String regex, boolean debug) {
Objects.requireNonNull(regex, "regex");
final List<Symbol> symbols = getSymbols();
SymbolChoice[][] options = new SymbolChoice[symbols.size()][];
int pos = 0;
int combinations = 1;
final SymbolChoice[] emptyChoice = new SymbolChoice[0];
for (Symbol symbol : getSymbols()) {
options[pos] = symbol.getSymbolChoices().toArray(emptyChoice);
combinations *= options[pos].length;
pos++;
}
Pattern pattern = Pattern.compile(regex);
int[] stack = new int[options.length];
int[] sbsize = new int[options.length + 1];
List<List<SymbolChoice>> listOfSymbolChoices = new ArrayList<List<SymbolChoice>>();
StringBuilder sb = new StringBuilder(stack.length);
int depth = 0;
int testcnt = 0;
while (depth >= 0) {
if (depth == options.length) {
Matcher matcher = pattern.matcher(sb);
testcnt++;
if (matcher.matches()) {
// we have a viable answer here, we can report it....
List<SymbolChoice> match = new ArrayList<>(stack.length);
for (int i = 0; i < stack.length; i++) {
match.add(options[i][stack[i]]);
}
listOfSymbolChoices.add(match);
}
depth--;
sb.setLength(sbsize[depth]);
stack[depth]++;
} else if (stack[depth] >= options[depth].length) {
stack[depth] = 0;
depth--;
if (depth >= 0) {
sb.setLength(sbsize[depth]);
stack[depth]++;
}
} else {
sb.append(options[depth][stack[depth]].symbol.value);
Matcher matcher = pattern.matcher(sb);
testcnt++;
if (matcher.find() || matcher.hitEnd()) {
// we have a viable answer here, we can descend....
depth++;
sbsize[depth] = sb.length();
} else {
// nothing viable down here....
sb.setLength(sbsize[depth]);
stack[depth]++;
}
}
}
public List<List<SymbolChoice>> forceFitRegex(final String regex) {
return forceFitRegex(regex, false);
}
public List<List<SymbolChoice>> forceFitRegex(final String regex, boolean debug) {
Objects.requireNonNull(regex, "regex");
final List<Symbol> symbols = getSymbols();
SymbolChoice[][] options = new SymbolChoice[symbols.size()][];
int pos = 0;
int combinations = 1;
final SymbolChoice[] emptyChoice = new SymbolChoice[0];
for (Symbol symbol : getSymbols()) {
options[pos] = symbol.getSymbolChoices().toArray(emptyChoice);
combinations *= options[pos].length;
pos++;
}
Pattern pattern = Pattern.compile(regex);
int[] stack = new int[options.length];
int[] sbsize = new int[options.length + 1];
List<List<SymbolChoice>> listOfSymbolChoices = new ArrayList<List<SymbolChoice>>();
StringBuilder sb = new StringBuilder(stack.length);
int depth = 0;
int testcnt = 0;
while (depth >= 0) {
if (stack[depth] >= options[depth].length) {
stack[depth] = 0;
depth--;
if (depth >= 0) {
sb.setLength(sbsize[depth]);
stack[depth]++;
}
} else {
sb.append(options[depth][stack[depth]].symbol.value);
Matcher matcher = pattern.matcher(sb);
testcnt++;
boolean found = matcher.matches();
if (depth == options.length - 1) {
if (found) {
// we have a viable answer here, we can report it....
List<SymbolChoice> match = new ArrayList<>(stack.length);
for (int i = 0; i < stack.length; i++) {
match.add(options[i][stack[i]]);
}
listOfSymbolChoices.add(match);
}
sb.setLength(sbsize[depth]);
stack[depth]++;
} else if (found || matcher.hitEnd()) {
// we have a viable answer here, we can descend....
depth++;
sbsize[depth] = sb.length();
} else {
// nothing viable down here....
sb.setLength(sbsize[depth]);
stack[depth]++;
}
}
}
if (debug) {
System.out.println("Combinations: " + combinations + " actual tests " + testcnt);
}
return listOfSymbolChoices;
}
Edit: Based on the hitEnd()
hint from maaartinus
if you are reading this, then consider upvoting his answer...
I have played with the code, and it is significantly faster... Consider this revised method (I won't pretend it is easy to read... - it is basically a state machine, though). I have put a test up on Ideone that processes 380M combinations in less than 2 seconds.....
public List<List<SymbolChoice>> forceFitRegex(final String regex) {
return forceFitRegex(regex, false);
}
public List<List<SymbolChoice>> forceFitRegex(final String regex, boolean debug) {
Objects.requireNonNull(regex, "regex");
final List<Symbol> symbols = getSymbols();
SymbolChoice[][] options = new SymbolChoice[symbols.size()][];
int pos = 0;
int combinations = 1;
final SymbolChoice[] emptyChoice = new SymbolChoice[0];
for (Symbol symbol : getSymbols()) {
options[pos] = symbol.getSymbolChoices().toArray(emptyChoice);
combinations *= options[pos].length;
pos++;
}
Pattern pattern = Pattern.compile(regex);
int[] stack = new int[options.length];
int[] sbsize = new int[options.length + 1];
List<List<SymbolChoice>> listOfSymbolChoices = new ArrayList<List<SymbolChoice>>();
StringBuilder sb = new StringBuilder(stack.length);
int depth = 0;
int testcnt = 0;
while (depth >= 0) {
if (depth == options.length) {
Matcher matcher = pattern.matcher(sb);
testcnt++;
if (matcher.matches()) {
// we have a viable answer here, we can report it....
List<SymbolChoice> match = new ArrayList<>(stack.length);
for (int i = 0; i < stack.length; i++) {
match.add(options[i][stack[i]]);
}
listOfSymbolChoices.add(match);
}
depth--;
sb.setLength(sbsize[depth]);
stack[depth]++;
} else if (stack[depth] >= options[depth].length) {
stack[depth] = 0;
depth--;
if (depth >= 0) {
sb.setLength(sbsize[depth]);
stack[depth]++;
}
} else {
sb.append(options[depth][stack[depth]].symbol.value);
Matcher matcher = pattern.matcher(sb);
testcnt++;
if (matcher.find() || matcher.hitEnd()) {
// we have a viable answer here, we can descend....
depth++;
sbsize[depth] = sb.length();
} else {
// nothing viable down here....
sb.setLength(sbsize[depth]);
stack[depth]++;
}
}
}
Edit: Based on the hitEnd()
hint from maaartinus
if you are reading this, then consider upvoting his answer...
I have played with the code, and it is significantly faster... Consider this revised method (I won't pretend it is easy to read... - it is basically a state machine, though). I have put a test up on Ideone that processes 380M combinations in less than 2 seconds.....
public List<List<SymbolChoice>> forceFitRegex(final String regex) {
return forceFitRegex(regex, false);
}
public List<List<SymbolChoice>> forceFitRegex(final String regex, boolean debug) {
Objects.requireNonNull(regex, "regex");
final List<Symbol> symbols = getSymbols();
SymbolChoice[][] options = new SymbolChoice[symbols.size()][];
int pos = 0;
int combinations = 1;
final SymbolChoice[] emptyChoice = new SymbolChoice[0];
for (Symbol symbol : getSymbols()) {
options[pos] = symbol.getSymbolChoices().toArray(emptyChoice);
combinations *= options[pos].length;
pos++;
}
Pattern pattern = Pattern.compile(regex);
int[] stack = new int[options.length];
int[] sbsize = new int[options.length + 1];
List<List<SymbolChoice>> listOfSymbolChoices = new ArrayList<List<SymbolChoice>>();
StringBuilder sb = new StringBuilder(stack.length);
int depth = 0;
int testcnt = 0;
while (depth >= 0) {
if (depth == options.length) {
Matcher matcher = pattern.matcher(sb);
testcnt++;
if (matcher.matches()) {
// we have a viable answer here, we can report it....
List<SymbolChoice> match = new ArrayList<>(stack.length);
for (int i = 0; i < stack.length; i++) {
match.add(options[i][stack[i]]);
}
listOfSymbolChoices.add(match);
}
depth--;
sb.setLength(sbsize[depth]);
stack[depth]++;
} else if (stack[depth] >= options[depth].length) {
stack[depth] = 0;
depth--;
if (depth >= 0) {
sb.setLength(sbsize[depth]);
stack[depth]++;
}
} else {
sb.append(options[depth][stack[depth]].symbol.value);
Matcher matcher = pattern.matcher(sb);
testcnt++;
if (matcher.find() || matcher.hitEnd()) {
// we have a viable answer here, we can descend....
depth++;
sbsize[depth] = sb.length();
} else {
// nothing viable down here....
sb.setLength(sbsize[depth]);
stack[depth]++;
}
}
}