From 67d90ffe78db98133064d6deb0c3905854150ecc Mon Sep 17 00:00:00 2001 From: axexlck Date: Sat, 7 Dec 2024 15:24:23 +0100 Subject: [PATCH] Improve `ReplacePart` --- .../core/builtin/ListFunctions.java | 10 +++--- .../core/visit/VisitorReplacePart.java | 36 ++++++++++++------- .../matheclipse/core/system/PatternsTest.java | 3 ++ 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ListFunctions.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ListFunctions.java index 78df0f15fe..378691755a 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ListFunctions.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/builtin/ListFunctions.java @@ -6211,25 +6211,27 @@ public IExpr evaluate(IAST ast, int argSize, IExpr[] option, EvalEngine engine, // Note: Rubi uses this kind of rule: return result.replacePart(lhs, rhs, heads).orElse(result); } + if (ast.arg2().isRuleAST()) { - return ast.arg1().replacePart((IAST) ast.arg2(), heads).orElse(ast.arg1()); + IAST ruleAST = (IAST) ast.arg2(); + return ast.arg1().replacePart(ruleAST.arg1(), ruleAST.arg2(), heads).orElse(ast.arg1()); } if (ast.arg2().isList()) { + IAST listAST = (IAST) ast.arg2(); if (ast.arg2().isListOfRules()) { - IExpr expr = result.replacePart((IAST) ast.arg2(), heads); + IExpr expr = result.replacePart(listAST, heads); if (expr.isPresent()) { result = expr; } return result; } - for (IExpr subList : (IAST) ast.arg2()) { + for (IExpr subList : listAST) { IExpr expr = result.replacePart(F.Rule(subList, ast.arg2()), heads); if (expr.isPresent()) { result = expr; } } - // return result.replacePart(F.Rule(ast.arg3(), ast.arg2()), heads).orElse(result); } return result; } diff --git a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorReplacePart.java b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorReplacePart.java index 68318e6a1c..15873625ef 100644 --- a/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorReplacePart.java +++ b/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/visit/VisitorReplacePart.java @@ -1,6 +1,5 @@ package org.matheclipse.core.visit; -import java.util.ArrayList; import org.matheclipse.core.eval.EvalEngine; import org.matheclipse.core.eval.exception.ReturnException; import org.matheclipse.core.expression.F; @@ -21,8 +20,9 @@ public class VisitorReplacePart extends AbstractVisitor { * A list of pattern matchers which should be matched against, for every possible position of an * {@link IAST} structure. */ - private ArrayList patternMatcherList; + private IPatternMatcher[] patternMatcherList; + private int listLength; /** * 0 or 1, depending if option Heads->True is set or the * 0 index position is used in the left-hand-side of a rule. @@ -49,7 +49,7 @@ public VisitorReplacePart(IAST rule, IExpr.COMPARE_TERNARY heads) { } if (rule.isListOfRules()) { IAST list = rule; - this.patternMatcherList = new ArrayList(list.argSize() + 3); + this.patternMatcherList = new IPatternMatcher[list.argSize()]; for (int i = 1; i < list.size(); i++) { rule = (IAST) list.get(i); @@ -66,7 +66,11 @@ public VisitorReplacePart(IAST rule, IExpr.COMPARE_TERNARY heads) { public VisitorReplacePart(IExpr lhs, IExpr rhs, IExpr.COMPARE_TERNARY heads) { super(); engine = EvalEngine.get(); - this.patternMatcherList = new ArrayList(1); + if (lhs.isList()) { + this.patternMatcherList = new IPatternMatcher[lhs.argSize()]; + } else { + this.patternMatcherList = new IPatternMatcher[1]; + } startOffset = heads == IExpr.COMPARE_TERNARY.TRUE ? 0 : 1; initPatternMatcher(lhs, rhs, heads); if (heads == COMPARE_TERNARY.FALSE) { @@ -106,7 +110,7 @@ private void initPatternMatcher(IExpr lhs, IExpr rhs, IExpr.COMPARE_TERNARY head } IPatternMatcher evalPatternMatcher = engine.evalPatternMatcher(F.Sequence(positions), rhs); - this.patternMatcherList.add(evalPatternMatcher); + this.patternMatcherList[listLength++] = evalPatternMatcher; } } else { if (list.argSize() > 0) { @@ -123,7 +127,7 @@ private void initPatternMatcher(IExpr lhs, IExpr rhs, IExpr.COMPARE_TERNARY head } IPatternMatcher evalPatternMatcher = engine.evalPatternMatcher(F.Sequence(positions), rhs); - this.patternMatcherList.add(evalPatternMatcher); + this.patternMatcherList[listLength++] = evalPatternMatcher; } } } else { @@ -135,17 +139,17 @@ private void initPatternMatcher(IExpr lhs, IExpr rhs, IExpr.COMPARE_TERNARY head startOffset = 0; } IPatternMatcher evalPatternMatcher = engine.evalPatternMatcher(F.Sequence(positions), rhs); - this.patternMatcherList.add(evalPatternMatcher); + this.patternMatcherList[listLength++] = evalPatternMatcher; } } catch (ReturnException rex) { if (fromPositions.isList()) { IAST list = ((IAST) fromPositions).apply(S.Sequence, 1); IPatternMatcher evalPatternMatcher = engine.evalPatternMatcher(list, rhs); - this.patternMatcherList.add(evalPatternMatcher); + this.patternMatcherList[listLength++] = evalPatternMatcher; } else { IPatternMatcher evalPatternMatcher = engine.evalPatternMatcher(fromPositions, rhs); - this.patternMatcherList.add(evalPatternMatcher); + this.patternMatcherList[listLength++] = evalPatternMatcher; } } } @@ -154,8 +158,11 @@ private IExpr visitPatternIndexList(IAST ast, IASTAppendable positions) { IASTAppendable result = F.NIL; for (int i = startOffset; i < ast.size(); i++) { final IInteger position = F.ZZ(i); - for (int j = 0; j < patternMatcherList.size(); j++) { - IPatternMatcher matcher = patternMatcherList.get(j); + for (int j = 0; j < listLength; j++) { + IPatternMatcher matcher = patternMatcherList[j]; + if (matcher == null) { + continue; + } IASTAppendable positionsToMatch = positions.copyAppendable(); positionsToMatch.append(position); @@ -251,8 +258,11 @@ private IASTAppendable patternIndexRecursive(IPatternMatcher matcher, IAST ast, @Override public IExpr visit(IASTMutable ast) { IASTAppendable positionsToMatch = F.ast(S.Sequence); - for (int j = 0; j < patternMatcherList.size(); j++) { - IPatternMatcher matcher = patternMatcherList.get(j); + for (int j = 0; j < listLength; j++) { + IPatternMatcher matcher = patternMatcherList[j]; + if (matcher == null) { + continue; + } IExpr lhs = matcher.getLHS(); if (lhs.isAST(S.Sequence, 1)) { // empty sequence matches with complete expression diff --git a/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/PatternsTest.java b/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/PatternsTest.java index b8bacb16a8..97bed8b8e1 100644 --- a/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/PatternsTest.java +++ b/symja_android_library/matheclipse-core/src/test/java/org/matheclipse/core/system/PatternsTest.java @@ -997,6 +997,9 @@ public void testReplacePartPattern() { @Test public void testReplacePartIntegerPositions() { + check("ReplacePart({a, b, c}, {{1}, {2}} -> t)", // + "{t,t,c}"); + check("ReplacePart({4,-1},-x,2)", // "{4,-x}"); check("ReplacePart({4,{1,3,7,11,19}},tt,{2,5})", //