You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
individual/src/JuniorQuestionGenerator.java

123 lines
4.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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();
}
}