Skip to content

Commit

Permalink
chore: fix issue dropping variables only in the numerator
Browse files Browse the repository at this point in the history
  • Loading branch information
justindujardin committed Feb 24, 2025
1 parent 5bc1419 commit 6080631
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 20 deletions.
19 changes: 8 additions & 11 deletions mathy_core/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,12 +580,18 @@ def __str__(self) -> str:
1. constant*variable -> 4x
2. fraction*variable -> 1/2x
3. constant*variable^power -> 4x^2
4. fraction*variable^power -> (1/2)x^2
"""
left, right = self._check()

# Handle fraction * variable cases
# Handle fraction * variable or fraction * power cases
if isinstance(left, DivideExpression):
if isinstance(right, (VariableExpression, PowerExpression)):
# Handle both direct variables and variables raised to a power
if isinstance(right, VariableExpression):
return self.with_color(f"({left}){right}")
elif isinstance(right, PowerExpression) and isinstance(
right.left, VariableExpression
):
return self.with_color(f"({left}){right}")

# Handle existing constant * variable cases
Expand All @@ -599,15 +605,6 @@ def __str__(self) -> str:

return super().__str__()

def to_math_ml_fragment(self) -> str:
left, right = self._check()
right_ml = right.to_math_ml_fragment()
left_ml = left.to_math_ml_fragment()
if isinstance(left, ConstantExpression):
if isinstance(right, (VariableExpression, PowerExpression)):
return f"{left_ml}{right_ml}"
return super().to_math_ml_fragment()


class DivideExpression(BinaryExpression):
"""Divide one by two"""
Expand Down
17 changes: 9 additions & 8 deletions mathy_core/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ def parse_factors(self) -> MathExpression:
if len(factors) == 0:
raise InvalidExpression("No factors")

# Handle power expressions for the last factor
exp: Optional[MathExpression] = None
if self.check(_IS_EXP):
opType = self.current_token.type
Expand All @@ -345,18 +346,18 @@ def parse_factors(self) -> MathExpression:
raise InvalidSyntax("Expected an expression after ^ operator")

right = self.parse_unary()
exp = PowerExpression(factors[-1], right)
# Create power expression from the last factor
factors[-1] = PowerExpression(factors[-1], right)

# Combine all factors with multiplication
if len(factors) == 1:
return exp or factors[0]
return factors[0]

while len(factors) > 0:
if exp is None:
exp = factors.pop(0)
# Build expression from left to right
exp = factors[0]
for i in range(1, len(factors)):
exp = MultiplyExpression(exp, factors[i])

exp = MultiplyExpression(exp, factors.pop(0))

assert exp is not None
return exp

def parse_function(self) -> MathExpression:
Expand Down
12 changes: 12 additions & 0 deletions mathy_core/rules/fraction_reduction.test.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
{
"valid": [
{
"why": "Training corner case regression",
"input": "9n + (8/10)n",
"output": "9n + (4/5)n",
"debug": true
},
{
"why": "Training corner case regression",
"input": "9n + 8n / 10",
"output": "9n + (4/5)n",
"debug": true
},
{
"why": "Simple numeric fraction",
"input": "(6x) / (3x)",
Expand Down
15 changes: 14 additions & 1 deletion mathy_core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def raise_with_history(

history_text: List[str] = []
if history is not None:
history_text = [f" - {h.raw}" for h in history]
history_text = [f"[{h.action}] - {h.raw}" for h in history]
history_text.insert(0, description)
tb = TracebackPrinter()
error = tb(title, "\n".join(history_text), tb=traceback.extract_stack())
Expand Down Expand Up @@ -738,6 +738,7 @@ def factor_fraction_terms_ex(

# Handle variables and exponents
if has_left and has_right and left_term.variable == right_term.variable:
# Both terms have the same variable
result.common_variable = left_term.variable

left_exp = left_term.exponent if left_term.exponent is not None else 1
Expand All @@ -752,6 +753,18 @@ def factor_fraction_terms_ex(
result.reduced_exponent = reduced_exp

result.common_exponent = min(left_exp, right_exp)
elif has_left and not has_right:
# Only numerator has a variable - preserve it
result.reduced_variable = left_term.variable
result.reduced_exponent = (
left_term.exponent if left_term.exponent is not None else 1
)
elif not has_left and has_right:
# Only denominator has a variable
result.reduced_variable = right_term.variable
result.reduced_exponent = -(
right_term.exponent if right_term.exponent is not None else 1
)
elif not (result.numerator != result.denominator):
return False

Expand Down

0 comments on commit 6080631

Please sign in to comment.