|
|
public class JuniorQuestionGenerator extends AbstractQuestionGenerator {
|
|
|
private static final String[] OPERATORS = {"+", "-", "×", "÷"};
|
|
|
private static boolean h = false;
|
|
|
private static StringBuilder q;
|
|
|
|
|
|
@Override
|
|
|
public String generateQuestion() {
|
|
|
int attempts = 0;
|
|
|
while (attempts < 100) {
|
|
|
attempts++;
|
|
|
|
|
|
int operandCount = random.nextInt(5) + 1; // 1~5个操作数
|
|
|
StringBuilder question = new StringBuilder();
|
|
|
boolean hasSpecialOperator = false;
|
|
|
|
|
|
AddSpecialOperator(operandCount, hasSpecialOperator, question);
|
|
|
hasSpecialOperator = h;
|
|
|
question = q;
|
|
|
|
|
|
|
|
|
String result = addReasonableParentheses(question.toString(), operandCount);
|
|
|
result = ensureBalancedParentheses(result);
|
|
|
|
|
|
// 检查平方后是否有运算符
|
|
|
if (!hasProperOperatorSpacing(result)) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if (isQuestionUnique(result) && isValidParentheses(result) &&
|
|
|
(hasOperator(result) || hasSpecialOperator)) {
|
|
|
addToGeneratedQuestions(result);
|
|
|
String regex = "(?<!\\s)\\)(?=[^)]*$)";
|
|
|
result = result.replaceAll(regex, " )");
|
|
|
return result;
|
|
|
}
|
|
|
}
|
|
|
return "√4 + 3²"; // 备用题目
|
|
|
}
|
|
|
|
|
|
private void AddSpecialOperator(int operandCount, boolean hasSpecialOperator, StringBuilder question) {
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
if (!hasSpecialOperator && random.nextDouble() < 0.4) {// 决定是否添加特殊运算符(平方或开方)
|
|
|
if (random.nextBoolean()) {
|
|
|
question.append(generateNumber()).append("²");
|
|
|
} else {
|
|
|
question.append("√").append(generateNumber());
|
|
|
}
|
|
|
hasSpecialOperator = true;
|
|
|
} else {
|
|
|
question.append(generateNumber());
|
|
|
}
|
|
|
if (i < operandCount - 1) {
|
|
|
String operator = generateOperator(OPERATORS);
|
|
|
question.append(" ").append(operator).append(" ");
|
|
|
}
|
|
|
}
|
|
|
if (!hasSpecialOperator) {// 如果还没有特殊运算符,强制添加一个
|
|
|
String[] parts = question.toString().split(" ");
|
|
|
int pos = random.nextInt(parts.length / 2 + 1) * 2;
|
|
|
if (pos >= parts.length) pos = parts.length - 1;
|
|
|
if (random.nextBoolean()) {
|
|
|
parts[pos] = parts[pos] + "²";
|
|
|
} else {
|
|
|
parts[pos] = "√" + parts[pos];
|
|
|
}
|
|
|
question = new StringBuilder(String.join(" ", parts));
|
|
|
hasSpecialOperator = true;
|
|
|
}
|
|
|
h = hasSpecialOperator;
|
|
|
q = question;
|
|
|
}
|
|
|
|
|
|
private boolean hasProperOperatorSpacing(String expression) {
|
|
|
String[] parts = expression.split(" ");
|
|
|
for (int i = 0; i < parts.length - 1; i++) {
|
|
|
// 如果当前部分是平方或开方,下一部分必须是运算符
|
|
|
if ((parts[i].endsWith("²") || parts[i].startsWith("√")) &&
|
|
|
i + 1 < parts.length && !isOperator(parts[i + 1])) {
|
|
|
return false;
|
|
|
}
|
|
|
// 如果当前部分是数字,下一部分不是运算符,也不合理
|
|
|
if (parts[i].matches("\\d+") && i + 1 < parts.length && !isOperator(parts[i + 1])) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
private boolean isOperator(String str) {
|
|
|
return str.equals("+") || str.equals("-") || str.equals("×") || str.equals("÷");
|
|
|
}
|
|
|
|
|
|
public String addReasonableParentheses(String expression, int operandCount) {
|
|
|
if (operandCount <= 2 || random.nextDouble() < 0.4) {
|
|
|
return expression;
|
|
|
}
|
|
|
|
|
|
String[] parts = expression.split(" ");
|
|
|
if (parts.length < 5) return expression;
|
|
|
|
|
|
StringBuilder newExpr = new StringBuilder();
|
|
|
int start = random.nextInt(Math.max(1, parts.length / 2 - 1));
|
|
|
int end = start + 1 + random.nextInt(Math.max(1, parts.length / 2 - start - 1));
|
|
|
|
|
|
for (int i = 0; i < parts.length; i++) {
|
|
|
if (i == start * 2 && start * 2 < parts.length - 3) {
|
|
|
newExpr.append("( ");
|
|
|
}
|
|
|
newExpr.append(parts[i]);
|
|
|
if (i == end * 2 && i < parts.length - 2 && end * 2 > start * 2 + 2) {
|
|
|
newExpr.append(" )");
|
|
|
}
|
|
|
if (i < parts.length - 1) {
|
|
|
newExpr.append(" ");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return newExpr.toString().trim();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|