|
|
|
|
@ -1,122 +1,127 @@
|
|
|
|
|
package mathpuzzle.service;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
import static mathpuzzle.service.PrimarySchoolGenerator.isNumeric;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Random;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 初中题目生成器
|
|
|
|
|
* 题目必须包含至少一个平方或开根号运算符
|
|
|
|
|
* 初中题目生成器 题目必须包含至少一个平方或开根号运算符
|
|
|
|
|
*/
|
|
|
|
|
public class JuniorHighGenerator implements QuestionGenerator {
|
|
|
|
|
private static final String[] ADVANCED_OPS = {"平方", "开根号"};
|
|
|
|
|
private static final String[] OPERATORS = {"+", "-", "*", "/"};
|
|
|
|
|
private final Random random = new Random();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<String> generateQuestions(int count) {
|
|
|
|
|
List<String> questions = new ArrayList<>();
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
String question = generateSingleQuestion();
|
|
|
|
|
questions.add(question);
|
|
|
|
|
}
|
|
|
|
|
return questions;
|
|
|
|
|
private static final String[] ADVANCED_OPS = {"平方", "开根号"};
|
|
|
|
|
private static final String[] OPERATORS = {"+", "-", "*", "/"};
|
|
|
|
|
private final Random random = new Random();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<String> generateQuestions(int count) {
|
|
|
|
|
List<String> questions = new ArrayList<>();
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
|
String question = generateSingleQuestion();
|
|
|
|
|
questions.add(question);
|
|
|
|
|
}
|
|
|
|
|
return questions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String generateSingleQuestion() {
|
|
|
|
|
List<String> parts = new ArrayList<>();
|
|
|
|
|
int operandCount = random.nextInt(5) + 1;
|
|
|
|
|
parts = generateBase(operandCount, parts);
|
|
|
|
|
// hasAdvancedOp用以检测下面的循环是否加入了高级运算符,如果没有就启动保底
|
|
|
|
|
boolean hasAdvancedOp = false;
|
|
|
|
|
if (operandCount == 1) {
|
|
|
|
|
if ("平方".equals(ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)])) {
|
|
|
|
|
parts.add("平方");
|
|
|
|
|
} else {
|
|
|
|
|
parts.set(0, "开根号" + parts.get(0));
|
|
|
|
|
}
|
|
|
|
|
hasAdvancedOp = true;
|
|
|
|
|
} else {
|
|
|
|
|
// 遍历查找左括号的合理位置
|
|
|
|
|
for(int i = 0; i < parts.size() - 2; i++) {
|
|
|
|
|
// 该位置要为操作数且随机添加括号
|
|
|
|
|
if (isNumeric(parts.get(i)) && random.nextBoolean()) {
|
|
|
|
|
// 随机数看取出来的是不是开根号运算符
|
|
|
|
|
if("开根号".equals(ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)])) {
|
|
|
|
|
parts = generateRoot(parts, i);
|
|
|
|
|
}
|
|
|
|
|
// 如果不是开根号就是平方运算
|
|
|
|
|
else {
|
|
|
|
|
parts = generateSquare(parts, i);
|
|
|
|
|
}
|
|
|
|
|
hasAdvancedOp = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private String generateSingleQuestion() {
|
|
|
|
|
List<String> parts = new ArrayList<>();
|
|
|
|
|
int operandCount = random.nextInt(5) + 1;
|
|
|
|
|
parts = generateBase(operandCount, parts);
|
|
|
|
|
// hasAdvancedOp用以检测下面的循环是否加入了高级运算符,如果没有就启动保底
|
|
|
|
|
boolean hasAdvancedOp = false;
|
|
|
|
|
if (operandCount == 1) {
|
|
|
|
|
if ("平方".equals(ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)])) {
|
|
|
|
|
parts.add("平方");
|
|
|
|
|
} else {
|
|
|
|
|
parts.set(0, "开根号" + parts.get(0));
|
|
|
|
|
}
|
|
|
|
|
hasAdvancedOp = true;
|
|
|
|
|
} else {
|
|
|
|
|
// 遍历查找左括号的合理位置
|
|
|
|
|
for (int i = 0; i < parts.size() - 2; i++) {
|
|
|
|
|
// 该位置要为操作数且随机添加括号
|
|
|
|
|
if (isNumeric(parts.get(i)) && random.nextBoolean()) {
|
|
|
|
|
// 随机数看取出来的是不是开根号运算符
|
|
|
|
|
if ("开根号".equals(ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)])) {
|
|
|
|
|
parts = generateRoot(parts, i);
|
|
|
|
|
}
|
|
|
|
|
// 如果不是开根号就是平方运算
|
|
|
|
|
else {
|
|
|
|
|
parts = generateSquare(parts, i);
|
|
|
|
|
}
|
|
|
|
|
hasAdvancedOp = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// 启动保底强制加入一个高级运算符
|
|
|
|
|
if(!hasAdvancedOp) {
|
|
|
|
|
parts = forceAddAdvancedOp(parts);
|
|
|
|
|
}
|
|
|
|
|
return String.join(" ", parts) + " =";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 产生基本操作
|
|
|
|
|
public List<String> generateBase(int operandCount, List<String> parts) {
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
int num = random.nextInt(100) + 1;
|
|
|
|
|
parts.add(String.valueOf(num));
|
|
|
|
|
if (i < operandCount - 1) {
|
|
|
|
|
parts.add(OPERATORS[random.nextInt(OPERATORS.length)]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
// 启动保底强制加入一个高级运算符
|
|
|
|
|
if (!hasAdvancedOp) {
|
|
|
|
|
parts = forceAddAdvancedOp(parts);
|
|
|
|
|
}
|
|
|
|
|
// 强制加入一个高级运算符
|
|
|
|
|
public List<String> forceAddAdvancedOp(List<String> parts) {
|
|
|
|
|
String advancedOp = ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)];
|
|
|
|
|
if ("平方".equals(advancedOp)) {
|
|
|
|
|
parts.add("平方");
|
|
|
|
|
} else { // 开根号
|
|
|
|
|
parts.set(0, "开根号(" + parts.get(0));
|
|
|
|
|
parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")" );
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
return String.join(" ", parts) + " =";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 产生基本操作
|
|
|
|
|
public List<String> generateBase(int operandCount, List<String> parts) {
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
int num = random.nextInt(100) + 1;
|
|
|
|
|
parts.add(String.valueOf(num));
|
|
|
|
|
if (i < operandCount - 1) {
|
|
|
|
|
parts.add(OPERATORS[random.nextInt(OPERATORS.length)]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 强制加入一个高级运算符
|
|
|
|
|
public List<String> forceAddAdvancedOp(List<String> parts) {
|
|
|
|
|
String advancedOp = ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)];
|
|
|
|
|
if ("平方".equals(advancedOp)) {
|
|
|
|
|
parts.add("平方");
|
|
|
|
|
} else { // 开根号
|
|
|
|
|
parts.set(0, "开根号(" + parts.get(0));
|
|
|
|
|
parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")");
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<String> generateRoot(List<String> parts, int i) {
|
|
|
|
|
if(random.nextBoolean()) {
|
|
|
|
|
parts.set(i, "开根号(" + parts.get(i) + ")");
|
|
|
|
|
} else {
|
|
|
|
|
parts.set(i, "开根号(" + parts.get(i));
|
|
|
|
|
// 为避免随机数上限出现0,此处要单独判断一下左括号正好括住倒数第二个操作数的情况
|
|
|
|
|
if (i == parts.size() - 3) {
|
|
|
|
|
parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")");
|
|
|
|
|
} else {
|
|
|
|
|
while(true) {
|
|
|
|
|
int i2 = random.nextInt(parts.size() - 3 - i) + 2;
|
|
|
|
|
if(isNumeric(parts.get(i + i2))) {
|
|
|
|
|
parts.set(i + i2, parts.get(i + i2) + ")");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public List<String> generateRoot(List<String> parts, int i) {
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
parts.set(i, "开根号(" + parts.get(i) + ")");
|
|
|
|
|
} else {
|
|
|
|
|
parts.set(i, "开根号(" + parts.get(i));
|
|
|
|
|
// 为避免随机数上限出现0,此处要单独判断一下左括号正好括住倒数第二个操作数的情况
|
|
|
|
|
if (i == parts.size() - 3) {
|
|
|
|
|
parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")");
|
|
|
|
|
} else {
|
|
|
|
|
while (true) {
|
|
|
|
|
int i2 = random.nextInt(parts.size() - 3 - i) + 2;
|
|
|
|
|
if (isNumeric(parts.get(i + i2))) {
|
|
|
|
|
parts.set(i + i2, parts.get(i + i2) + ")");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<String> generateSquare(List<String> parts, int i) {
|
|
|
|
|
parts.set(i, "(" + parts.get(i));
|
|
|
|
|
// 为避免随机数上限出现0,此处要单独判断一下左括号正好括住倒数第二个操作数的情况
|
|
|
|
|
if (i == parts.size() - 3) {
|
|
|
|
|
parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")");
|
|
|
|
|
} else {
|
|
|
|
|
while(true) {
|
|
|
|
|
int i2 = random.nextInt(parts.size() - 3 - i) + 2;
|
|
|
|
|
if(isNumeric(parts.get(i + i2))) {
|
|
|
|
|
parts.set(i + i2, parts.get(i + i2) + ")平方");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public List<String> generateSquare(List<String> parts, int i) {
|
|
|
|
|
parts.set(i, "(" + parts.get(i));
|
|
|
|
|
// 为避免随机数上限出现0,此处要单独判断一下左括号正好括住倒数第二个操作数的情况
|
|
|
|
|
if (i == parts.size() - 3) {
|
|
|
|
|
parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")");
|
|
|
|
|
} else {
|
|
|
|
|
while (true) {
|
|
|
|
|
int i2 = random.nextInt(parts.size() - 3 - i) + 2;
|
|
|
|
|
if (isNumeric(parts.get(i + i2))) {
|
|
|
|
|
parts.set(i + i2, parts.get(i + i2) + ")平方");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return parts;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|