diff --git a/src/PowerManager.java b/src/PowerManager.java index b3ba370..f4c7295 100644 --- a/src/PowerManager.java +++ b/src/PowerManager.java @@ -1,95 +1,148 @@ -import java.util.List; -import java.util.Random; - -/** - * 负责添加幂运算 - */ -public class PowerManager { - private static final Random RANDOM = new Random(); - - // 普通幂运算 - public String addPowerOperations(String expression, List numPositions) { - if (numPositions.isEmpty()) return expression; - - String[] tokens = expression.split(" "); - int targetIndex = chooseTargetIndex(tokens, numPositions, null); - - if (targetIndex != -1) { - tokens[targetIndex] = applyPower(tokens[targetIndex], tokens, targetIndex); - } - - return String.join(" ", tokens); - } - - // 避免加在 trig 已占用的位置,同时避免加在运算符右边 - public String addPowerOperationsAvoid(String expression, List numPositions, List trigPositions) { - if (numPositions.isEmpty()) return expression; - - String[] tokens = expression.split(" "); - int targetIndex = chooseTargetIndex(tokens, numPositions, trigPositions); - - if (targetIndex != -1) { - tokens[targetIndex] = applyPower(tokens[targetIndex], tokens, targetIndex); - } - - return String.join(" ", tokens); - } - - // 选择合适的位置加幂运算 - private int chooseTargetIndex(String[] tokens, List numPositions, List avoidPositions) { - for (int tries = 0; tries < 20; tries++) { - int idx = numPositions.get(RANDOM.nextInt(numPositions.size())); - - if ((avoidPositions == null || !avoidPositions.contains(idx)) && canApplyPower(tokens, idx)) { - return idx; - } - } - return -1; - } - - // 检查该位置是否可以加幂运算 - private boolean canApplyPower(String[] tokens, int index) { - if (!isNumber(tokens[index])) return false; - if (tokens[index].contains("^") || tokens[index].contains("√")) return false; // 避免重复幂运算 - - // 不能加在运算符右边 - if (index > 0) { - String prev = tokens[index - 1]; - if (prev.equals("/") || prev.equals("*") || prev.equals("+") || prev.equals("-")) { - return false; - } - } - return true; - } - - // 应用平方或开方(根号放左括号左侧,平方放右括号右侧) - private String applyPower(String token, String[] tokens, int index) { - boolean useSqrt = RANDOM.nextBoolean(); - - if (useSqrt) { - // 根号放在左括号左侧,如果前面是左括号,则放在括号左边 - if (index > 0 && tokens[index - 1].equals(")")) { - return "√" + token; // 特殊情况,仍然放数字前 - } - if (index > 0 && tokens[index - 1].equals("(")) { - return "√" + token; - } - return "√" + token; - } else { - // 平方放在右括号右侧,如果后面是右括号,则放在括号右边 - if (index < tokens.length - 1 && tokens[index + 1].equals(")")) { - return token + "^2"; - } - return token + "^2"; - } - } - - private boolean isNumber(String token) { - try { - Integer.parseInt(token); - return true; - } catch (NumberFormatException e) { - return false; - } - } -} +import java.util.List; +import java.util.ArrayList; +import java.util.Random; + +public class PowerManager { + private static final Random RANDOM = new Random(); + + //添加一次幂运算,30%概率再加一次 + public String addPowerOperations(String expression, List numPositions, + List trigPositions) { + if (numPositions.isEmpty()) { + return expression; + } + + String[] tokens = expression.split(" "); + + addOnePower(tokens, numPositions, trigPositions); + if (RANDOM.nextDouble() < 0.3) { + addOnePower(tokens, numPositions, trigPositions); + } + + return String.join(" ", tokens); + } + + // 添加一次幂运算,平方/根号各50% + private void addOnePower(String[] tokens, List numPositions, List trigPositions) { + if (RANDOM.nextBoolean()) { + tryAddSquare(tokens, numPositions, trigPositions); + } else { + tryAddSqrt(tokens, numPositions, trigPositions); + } + } + + // 添加平方 + private void tryAddSquare(String[] tokens, List numPositions, + List trigPositions) { + int target = chooseTargetIndex(tokens, numPositions, trigPositions, true); + if (target != -1) { + tokens[target] = tokens[target] + "^2"; + } + } + + // 添加根号 + private void tryAddSqrt(String[] tokens, List numPositions, + List trigPositions) { + int target = chooseTargetIndex(tokens, numPositions, trigPositions, false); + if (target != -1) { + tokens[target] = "√" + tokens[target]; + } + } + + // 选择可插入位置 + private int chooseTargetIndex(String[] tokens, List numPositions, + List trigPositions, boolean isSquare) { + List candidates = new ArrayList<>(); + for (int idx : numPositions) { + String token = tokens[idx]; + + // 避免 trig 位置 + if (trigPositions != null && trigPositions.contains(idx)) { + continue; + } + // 不能已有运算 + if (token.contains("^") || token.contains("√")) { + continue; + } + // 括号匹配检查 + if ((token.equals("(") || token.equals(")")) && !checkParenCanAdd(tokens, idx, isSquare)) { + continue; + } + + // 根号/平方合法性 + if (isSquare) { + if (isNumber(token) || token.equals(")")) { + candidates.add(idx); + } + } + if (!isSquare) { + if (isNumber(token) || token.equals("(")) { + candidates.add(idx); + } + } + } + + if (candidates.isEmpty()) { + return -1; + } + return candidates.get(RANDOM.nextInt(candidates.size())); + } + + // 检查括号匹配另一侧是否可以加运算 + private boolean checkParenCanAdd(String[] tokens, int index, boolean isSquare) { + int match = findMatchingParen(tokens, index); + if (match == -1) { + return false; + } + + // 检查匹配括号是否已加运算 + if (tokens[match].contains("^") || tokens[match].contains("√")) { + return false; + } + + // 左括号只能加根号,右括号只能加平方 + if (isSquare && tokens[index].equals("(")) { + return false; + } + return isSquare || !tokens[index].equals(")"); + } + + // 找匹配括号 + private int findMatchingParen(String[] tokens, int index) { + if (tokens[index].equals("(")) { + int depth = 0; + for (int i = index; i < tokens.length; i++) { + if (tokens[i].equals("(")) { + depth++; + } else if (tokens[i].equals(")")) { + depth--; + if (depth == 0) { + return i; + } + } + } + } else if (tokens[index].equals(")")) { + int depth = 0; + for (int i = index; i >= 0; i--) { + if (tokens[i].equals(")")) { + depth++; + } else if (tokens[i].equals("(")) { + depth--; + if (depth == 0) { + return i; + } + } + } + } + return -1; + } + + private boolean isNumber(String token) { + try { + Integer.parseInt(token); + return true; + } catch (NumberFormatException e) { + return false; + } + } +}