V1 untested
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#Steps that are generated
|
||||
|
||||
from sympy import *
|
||||
import re
|
||||
from sympy.parsing.sympy_parser import (
|
||||
parse_expr,
|
||||
standard_transformations,
|
||||
@@ -94,8 +95,8 @@ def multiply_both_sides(equation, value):
|
||||
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
||||
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
||||
|
||||
new_left_expr = left_expr * value
|
||||
new_right_expr = right_expr * value
|
||||
new_left_expr = cancel(left_expr * value)
|
||||
new_right_expr = Mul(right_expr, value, evaluate=False)
|
||||
step["after"] = f"{sstr(new_left_expr)} = {sstr(new_right_expr)}"
|
||||
|
||||
step["step"] = f"Multiply both sides by {sstr(value)}"
|
||||
@@ -253,8 +254,12 @@ def trinomial_by_grouping(equation, inner):
|
||||
new_left_expr = left_expr
|
||||
|
||||
steps[-1]["after"] = f"{sstr(new_left_expr)} = {sstr(right_expr)}"
|
||||
steps[-1]["step"] = f"Seperate the x coeficients equal to the factors of {sstr(ac)} that {action} {sstr(Abs(b))}"
|
||||
steps[-1]["rule"] = "Split Coeficients"
|
||||
steps[-1]["step"] = (
|
||||
f"Seperate the x coefficient to equal the factors of the first times last coefficients"
|
||||
f"({sstr(Abs(a))} x {sstr(Abs(c))} = {sstr(ac)}) that {action} {sstr(Abs(b))}"
|
||||
f"({sstr(factor1)},{sstr(factor2)})"
|
||||
)
|
||||
steps[-1]["rule"] = "Split Coefficients"
|
||||
|
||||
## Factor Out X on left term
|
||||
steps.append({})
|
||||
@@ -262,6 +267,7 @@ def trinomial_by_grouping(equation, inner):
|
||||
|
||||
terms = left_expr.as_ordered_terms()
|
||||
t1, t2, t3, t4 = terms[0], terms[1], terms[2], terms[3]
|
||||
div = gcd(t3, t4)
|
||||
factored_part1 = factor(t1 + t2)
|
||||
factored_part2 = factor(t3 + t4)
|
||||
rest = sum(terms[2:])
|
||||
@@ -280,7 +286,7 @@ def trinomial_by_grouping(equation, inner):
|
||||
new_left_expr = Mul(n, left_expr, evaluate=False)
|
||||
|
||||
steps[-1]["after"] = f"{sstr(new_left_expr)} = {sstr(right_expr)}"
|
||||
steps[-1]["step"] = f"Factor out the GCD from the right two terms of the inner polynomial"
|
||||
steps[-1]["step"] = f"Factor out the GCD({sstr(div)}) from the right two terms of the inner polynomial"
|
||||
steps[-1]["rule"] = "Reverse Distributive Property"
|
||||
|
||||
## Add Like Terms
|
||||
@@ -311,9 +317,30 @@ def solve_roots(equation):
|
||||
x = symbols('x')
|
||||
|
||||
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
||||
factors = left_expr.as_ordered_factors()
|
||||
x_factors = [f for f in factors if f.has(x)]
|
||||
|
||||
## Get the roots
|
||||
factors = left_expr.as_ordered_factors()
|
||||
x_factors = []
|
||||
|
||||
i = 0
|
||||
while i < len(factors):
|
||||
f = factors[i]
|
||||
|
||||
if f.has(x):
|
||||
# If it's already something like 2*x or (x+...)
|
||||
x_factors.append(f)
|
||||
i += 1
|
||||
else:
|
||||
# Check if next factor has x → combine them
|
||||
if i + 1 < len(factors) and factors[i + 1].has(x) and not factors[i + 1].is_Add:
|
||||
combined = Mul(f, factors[i + 1], evaluate=False)
|
||||
x_factors.append(combined)
|
||||
i += 2
|
||||
else:
|
||||
i += 1
|
||||
|
||||
|
||||
## Iterate through the roots
|
||||
solutions = ""
|
||||
for factor in x_factors:
|
||||
clean_factor = clean(factor)
|
||||
@@ -399,7 +426,7 @@ def combine_like_terms(equation):
|
||||
step["rule"] = "Combine the like terms"
|
||||
return step
|
||||
|
||||
def distribute_step(equation):
|
||||
def distribute_left_step(equation):
|
||||
steps = []
|
||||
|
||||
current = equation
|
||||
@@ -416,12 +443,101 @@ def distribute_step(equation):
|
||||
if distributed != None:
|
||||
steps.append({})
|
||||
steps[-1]["before"] = current
|
||||
steps[-1]["after"] = f"{sstr(safe_format(new_left_expr))} = {sstr(right_expr)}"
|
||||
steps[-1]["after"] = f"{sstr(safe_format(new_left_expr))} = {sstr(safe_format(right_expr))}"
|
||||
steps[-1]["step"] = f"Distribute out {sstr(distributed)}"
|
||||
steps[-1]["rule"] = "Distributive Law of Multiplication"
|
||||
|
||||
return steps
|
||||
|
||||
def distribute_right_step(equation):
|
||||
steps = []
|
||||
|
||||
current = equation
|
||||
left, right = current.split("=")
|
||||
left = left.replace("-(", "-1*(")
|
||||
x = symbols('x')
|
||||
|
||||
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
||||
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
||||
|
||||
#print(f"calling distribute_once with expression: {sstr(left_expr)}")
|
||||
new_right_expr, distributed = distribute_once(right_expr)
|
||||
|
||||
if distributed != None:
|
||||
steps.append({})
|
||||
steps[-1]["before"] = current
|
||||
steps[-1]["after"] = f"{sstr(safe_format(left_expr))} = {sstr(safe_format(new_right_expr))}"
|
||||
steps[-1]["step"] = f"Distribute out {sstr(distributed)}"
|
||||
steps[-1]["rule"] = "Distributive Law of Multiplication"
|
||||
|
||||
return steps
|
||||
|
||||
def check_roots(equation, roots):
|
||||
steps = []
|
||||
|
||||
valid_roots = ""
|
||||
str_values = [r.split("=")[1].strip() for r in roots.split(",")]
|
||||
values = [sympify(value) for value in str_values]
|
||||
current = equation
|
||||
left, right = current.split("=")
|
||||
x = symbols('x')
|
||||
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
||||
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
||||
|
||||
# Check the roots
|
||||
for value in values:
|
||||
## Substitution
|
||||
left_subbed = substitute_var(left, 'x', f"{value}")
|
||||
right_subbed = substitute_var(right, 'x', f"{value}")
|
||||
left_subbed_exp = parse_expr(left_subbed)
|
||||
right_subbed_exp = parse_expr(right_subbed)
|
||||
steps.append({})
|
||||
steps[-1]["before"] = equation
|
||||
steps[-1]["after"] = f"{left_subbed} = {right_subbed}"
|
||||
steps[-1]["step"] = f"Substitute x with {value}"
|
||||
steps[-1]["rule"] = "Substitution"
|
||||
## Check
|
||||
l_result = simplify(left_subbed_exp)
|
||||
r_result = simplify(right_subbed_exp)
|
||||
if l_result in (zoo, oo, -oo, nan) or r_result in (zoo, oo, -oo, nan):
|
||||
steps.append({})
|
||||
steps[-1]["before"] = steps[-2]["after"]
|
||||
steps[-1]["after"] = f"Undefined"
|
||||
steps[-1]["step"] = f"Found Extraneous Root, {value} is incorrect"
|
||||
steps[-1]["rule"] = "Extraneous Root"
|
||||
continue
|
||||
|
||||
if l_result != r_result:
|
||||
steps.append({})
|
||||
steps[-1]["before"] = steps[-2]["after"]
|
||||
steps[-1]["after"] = f"{sstr(l_result)} ≠ {sstr(r_result)}"
|
||||
steps[-1]["step"] = f"Found Extraneous Root, {value} is incorrect"
|
||||
steps[-1]["rule"] = "Extraneous Root"
|
||||
continue
|
||||
|
||||
else:
|
||||
steps.append({})
|
||||
steps[-1]["before"] = steps[-2]["after"]
|
||||
steps[-1]["after"] = f"{sstr(l_result)} = {sstr(r_result)}"
|
||||
steps[-1]["step"] = f"{value} is correct"
|
||||
steps[-1]["rule"] = "Found Root"
|
||||
if len(valid_roots) > 0:
|
||||
valid_roots += ","
|
||||
valid_roots += f"x = {value}"
|
||||
|
||||
|
||||
steps.append({})
|
||||
steps[-1]["before"] = equation
|
||||
steps[-1]["after"] = valid_roots
|
||||
steps[-1]["step"] = f"Found Valid Roots"
|
||||
steps[-1]["rule"] = "Found Solution"
|
||||
|
||||
return steps
|
||||
|
||||
def substitute_var(expr, var, value):
|
||||
pattern = rf'\b{re.escape(var)}\b'
|
||||
return re.sub(pattern, f'({value})', expr)
|
||||
|
||||
def build_ordered_add(args):
|
||||
flat_args = []
|
||||
|
||||
@@ -521,12 +637,35 @@ def clean(expr):
|
||||
def safe_format(expr):
|
||||
if expr.is_Mul:
|
||||
args = []
|
||||
sign = 1
|
||||
|
||||
for a in expr.args:
|
||||
a = safe_format(a)
|
||||
|
||||
if a == 1:
|
||||
continue
|
||||
args.append(a)
|
||||
return Mul(*args, evaluate=False)
|
||||
elif a == -1:
|
||||
sign *= -1
|
||||
else:
|
||||
args.append(a)
|
||||
|
||||
if not args:
|
||||
return -1 if sign == -1 else 1
|
||||
|
||||
# if everything is numeric → evaluate fully
|
||||
if all(a.is_Number for a in args):
|
||||
val = Mul(*args)
|
||||
return -val if sign == -1 else val
|
||||
|
||||
if len(args) == 1:
|
||||
result = args[0]
|
||||
else:
|
||||
result = Mul(*args, evaluate=False)
|
||||
|
||||
if sign == -1:
|
||||
return Mul(-1, result, evaluate=False)
|
||||
|
||||
return result
|
||||
|
||||
if expr.is_Add:
|
||||
return expr.func(*[safe_format(a) for a in expr.args], evaluate=False)
|
||||
|
||||
Reference in New Issue
Block a user