print statements in places
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -56,8 +56,8 @@ def subtract_both_sides(equation, value):
|
|||||||
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
||||||
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
||||||
|
|
||||||
new_left_expr = left_expr - value
|
new_left_expr = clean(left_expr - value)
|
||||||
new_right_expr = right_expr - value
|
new_right_expr = clean(right_expr - value)
|
||||||
step["after"] = f"{sstr(new_left_expr)} = {sstr(new_right_expr)}"
|
step["after"] = f"{sstr(new_left_expr)} = {sstr(new_right_expr)}"
|
||||||
|
|
||||||
step["step"] = f"Subtract both sides by {sstr(value)}"
|
step["step"] = f"Subtract both sides by {sstr(value)}"
|
||||||
@@ -101,6 +101,44 @@ def multiply_both_sides(equation, value):
|
|||||||
step["step"] = f"Multiply both sides by {sstr(value)}"
|
step["step"] = f"Multiply both sides by {sstr(value)}"
|
||||||
step["rule"] = "Multiplication Property of Equality"
|
step["rule"] = "Multiplication Property of Equality"
|
||||||
return step
|
return step
|
||||||
|
|
||||||
|
def square_root_both_sides(equation):
|
||||||
|
step = {}
|
||||||
|
|
||||||
|
current = equation
|
||||||
|
step["before"] = current
|
||||||
|
left, right = current.split("=")
|
||||||
|
x_generic = symbols('x')
|
||||||
|
x_pos = symbols('x', positive=True)
|
||||||
|
|
||||||
|
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
||||||
|
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
||||||
|
|
||||||
|
new_left_expr = sqrt(left_expr.subs(x_generic, x_pos))
|
||||||
|
new_right_expr = sqrt(right_expr)
|
||||||
|
step["after"] = f"{sstr(new_left_expr)} = {sstr(new_right_expr)}, {sstr(new_left_expr)} = -{sstr(new_right_expr)}"
|
||||||
|
|
||||||
|
step["step"] = f"Take the square root of both sides"
|
||||||
|
step["rule"] = "Square Root Property of Equality"
|
||||||
|
return step
|
||||||
|
|
||||||
|
def square_both_sides(equation):
|
||||||
|
step = {}
|
||||||
|
|
||||||
|
current = equation
|
||||||
|
step["before"] = current
|
||||||
|
left, right = current.split("=")
|
||||||
|
|
||||||
|
left_expr = parse_expr(left, transformations=transformations, evaluate=False)
|
||||||
|
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
||||||
|
|
||||||
|
new_left_expr = clean(left_expr * left_expr)
|
||||||
|
new_right_expr = clean(right_expr * right_expr)
|
||||||
|
step["after"] = f"{sstr(new_left_expr)} = {sstr(new_right_expr)}"
|
||||||
|
|
||||||
|
step["step"] = f"Square both sides"
|
||||||
|
step["rule"] = "Multiplication property of equality"
|
||||||
|
return step
|
||||||
|
|
||||||
def factor_collect(equation):
|
def factor_collect(equation):
|
||||||
step = {}
|
step = {}
|
||||||
@@ -122,6 +160,7 @@ def factor_collect(equation):
|
|||||||
return step
|
return step
|
||||||
|
|
||||||
def factor_form_collection(equation, factor):
|
def factor_form_collection(equation, factor):
|
||||||
|
# Collect factors of factor
|
||||||
step = {}
|
step = {}
|
||||||
|
|
||||||
current = equation
|
current = equation
|
||||||
@@ -140,6 +179,180 @@ def factor_form_collection(equation, factor):
|
|||||||
step["rule"] = "Factor by grouping"
|
step["rule"] = "Factor by grouping"
|
||||||
return step
|
return step
|
||||||
|
|
||||||
|
def factor_out(equation, factor):
|
||||||
|
step = {}
|
||||||
|
|
||||||
|
current = equation
|
||||||
|
step["before"] = current
|
||||||
|
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)
|
||||||
|
|
||||||
|
new_left_expr = clean(cancel(left_expr / factor))
|
||||||
|
new_left_expr = Mul(factor, new_left_expr, evaluate = False)
|
||||||
|
step["after"] = f"{sstr(new_left_expr)} = {sstr(right_expr)}"
|
||||||
|
|
||||||
|
step["step"] = f"Factor out the Greatest Common Factor, {sstr(factor)}"
|
||||||
|
step["rule"] = "Reverse Distributive Property"
|
||||||
|
return step
|
||||||
|
|
||||||
|
def trinomial_by_grouping(equation, inner):
|
||||||
|
# expects n (ax**2+bx+c) = rhs : inner = (ax**2+bx+c), b != 0, c != 0
|
||||||
|
|
||||||
|
#4 steps
|
||||||
|
steps = [{}]
|
||||||
|
|
||||||
|
current = equation
|
||||||
|
steps[-1]["before"] = current
|
||||||
|
left, right = current.split("=")
|
||||||
|
x = symbols('x')
|
||||||
|
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
right_expr = parse_expr(right, transformations=transformations, evaluate=False)
|
||||||
|
n = simplify(left_expr / inner)
|
||||||
|
poly = inner.as_poly(x)
|
||||||
|
a = poly.coeff_monomial(x**2)
|
||||||
|
b = poly.coeff_monomial(x)
|
||||||
|
c = poly.coeff_monomial(1)
|
||||||
|
ac = Abs(a * c)
|
||||||
|
|
||||||
|
## Split Coeficients
|
||||||
|
factor1 = Integer(1)
|
||||||
|
factor2 = ac
|
||||||
|
while factor1 < factor2:
|
||||||
|
if ac % factor1 == 0:
|
||||||
|
factor2 = ac / factor1
|
||||||
|
if c.is_negative:
|
||||||
|
if Abs(factor1 - factor2) == Abs(b):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if factor1 + factor2 == Abs(b):
|
||||||
|
break
|
||||||
|
factor1 = factor1 + 1
|
||||||
|
|
||||||
|
if factor1 > factor2:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if c.is_negative:
|
||||||
|
action = "differ by"
|
||||||
|
if b.is_negative:
|
||||||
|
left_expr = Add(a * x**2, factor1 * x, -factor2 * x, c, evaluate=False)
|
||||||
|
else:
|
||||||
|
left_expr = Add(a * x**2, -factor1 * x, factor2 * x, c, evaluate=False)
|
||||||
|
else:
|
||||||
|
action = "add up to"
|
||||||
|
if b.is_negative:
|
||||||
|
left_expr = Add(a * x**2, -factor1 * x, -factor2 * x, c, evaluate=False)
|
||||||
|
else:
|
||||||
|
left_expr = Add(a * x**2, factor1 * x, factor2 * x, c, evaluate=False)
|
||||||
|
if n != 1:
|
||||||
|
new_left_expr = Mul(n, left_expr, evaluate=False)
|
||||||
|
else:
|
||||||
|
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"
|
||||||
|
|
||||||
|
## Factor Out X on left term
|
||||||
|
steps.append({})
|
||||||
|
steps[-1]["before"] = steps[-2]["after"]
|
||||||
|
|
||||||
|
terms = left_expr.as_ordered_terms()
|
||||||
|
t1, t2, t3, t4 = terms[0], terms[1], terms[2], terms[3]
|
||||||
|
factored_part1 = factor(t1 + t2)
|
||||||
|
factored_part2 = factor(t3 + t4)
|
||||||
|
rest = sum(terms[2:])
|
||||||
|
new_left_expr = Add(factored_part1, rest, evaluate=False)
|
||||||
|
new_left_expr = Mul(n, new_left_expr, evaluate=False)
|
||||||
|
|
||||||
|
steps[-1]["after"] = f"{sstr(new_left_expr)} = {sstr(right_expr)}"
|
||||||
|
steps[-1]["step"] = f"Factor out the x from the left two terms of the inner polynomial"
|
||||||
|
steps[-1]["rule"] = "Reverse Distributive Property"
|
||||||
|
|
||||||
|
## Factor Out GCD on right term
|
||||||
|
steps.append({})
|
||||||
|
steps[-1]["before"] = steps[-2]["after"]
|
||||||
|
|
||||||
|
left_expr = Add(factored_part1, factored_part2, evaluate=False)
|
||||||
|
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]["rule"] = "Reverse Distributive Property"
|
||||||
|
|
||||||
|
## Add Like Terms
|
||||||
|
if steps[-1]["before"] != steps[-1]["after"]:
|
||||||
|
steps.append({})
|
||||||
|
steps[-1]["before"] = steps[-2]["after"]
|
||||||
|
terms = left_expr.as_ordered_terms()
|
||||||
|
factors = [set(t.as_ordered_factors()) for t in terms]
|
||||||
|
common = set.intersection(*factors)
|
||||||
|
base = list(common)[0]
|
||||||
|
coeffs = [t.coeff(base) for t in terms]
|
||||||
|
new_expr = sum(coeffs) * base
|
||||||
|
new_left_expr = flatten_mul(Mul(n, new_expr, evaluate=False))
|
||||||
|
|
||||||
|
steps[-1]["after"] = f"{sstr(new_left_expr)} = {sstr(right_expr)}"
|
||||||
|
steps[-1]["step"] = f"Collect the like terms"
|
||||||
|
steps[-1]["rule"] = "Combine the like terms"
|
||||||
|
|
||||||
|
return steps
|
||||||
|
|
||||||
|
def solve_roots(equation):
|
||||||
|
# expects n(ax+b)(x+c) = 0
|
||||||
|
|
||||||
|
#4 steps
|
||||||
|
steps = []
|
||||||
|
|
||||||
|
left, right = equation.split("=")
|
||||||
|
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)]
|
||||||
|
|
||||||
|
solutions = ""
|
||||||
|
for factor in x_factors:
|
||||||
|
clean_factor = clean(factor)
|
||||||
|
steps.append({})
|
||||||
|
if solutions:
|
||||||
|
solutions = solutions + ", "
|
||||||
|
steps[-1]["before"] = equation
|
||||||
|
steps[-1]["after"] = f"{sstr(clean_factor)} = 0"
|
||||||
|
steps[-1]["step"] = f"Focus on a root"
|
||||||
|
steps[-1]["rule"] = "Root of a polynomial"
|
||||||
|
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
a = clean_factor.coeff(x)
|
||||||
|
b = clean_factor.subs(x, 0)
|
||||||
|
if b.is_zero == False:
|
||||||
|
if b.is_negative:
|
||||||
|
steps.append(add_both_sides(current, -b))
|
||||||
|
elif b.is_positive:
|
||||||
|
steps.append(subtract_both_sides(current, b))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left)
|
||||||
|
right_expr = parse_expr(right)
|
||||||
|
steps[-1]["after"] = f"{sstr(left_expr)} = {sstr(right_expr)}"
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
if a != 1 and a != -1:
|
||||||
|
steps.append(divide_both_sides(current, a))
|
||||||
|
elif a == -1:
|
||||||
|
steps.append(multiply_both_sides(current, a))
|
||||||
|
solutions += steps[-1]["after"]
|
||||||
|
|
||||||
|
steps.append({})
|
||||||
|
steps[-1]["before"] = equation
|
||||||
|
steps[-1]["after"] = solutions
|
||||||
|
steps[-1]["step"] = f"Solved The Roots"
|
||||||
|
steps[-1]["rule"] = "Root of a polynomial"
|
||||||
|
|
||||||
|
return steps
|
||||||
|
|
||||||
def combine_like_terms(equation):
|
def combine_like_terms(equation):
|
||||||
step = {}
|
step = {}
|
||||||
|
|
||||||
@@ -186,6 +399,110 @@ def combine_like_terms(equation):
|
|||||||
step["rule"] = "Combine the like terms"
|
step["rule"] = "Combine the like terms"
|
||||||
return step
|
return step
|
||||||
|
|
||||||
|
def distribute_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_left_expr, distributed = distribute_once(left_expr)
|
||||||
|
|
||||||
|
if distributed != None:
|
||||||
|
steps.append({})
|
||||||
|
steps[-1]["before"] = current
|
||||||
|
steps[-1]["after"] = f"{sstr(safe_format(new_left_expr))} = {sstr(right_expr)}"
|
||||||
|
steps[-1]["step"] = f"Distribute out {sstr(distributed)}"
|
||||||
|
steps[-1]["rule"] = "Distributive Law of Multiplication"
|
||||||
|
|
||||||
|
return steps
|
||||||
|
|
||||||
|
def build_ordered_add(args):
|
||||||
|
expr = args[0]
|
||||||
|
for a in args[1:]:
|
||||||
|
expr = Add(expr, a, evaluate=False)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def distribute_once(expr):
|
||||||
|
expr = flatten_mul(expr)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# STEP 1: ONLY HANDLE DIRECT DISTRIBUTION CASES
|
||||||
|
# (i.e. Mul where one factor is Add)
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
if expr.is_Mul:
|
||||||
|
|
||||||
|
print(f"expr: {sstr(expr)}")
|
||||||
|
|
||||||
|
add_part = None
|
||||||
|
other_parts = []
|
||||||
|
|
||||||
|
# extract Add factor + everything else
|
||||||
|
for arg in expr.args:
|
||||||
|
print(f"arg: {sstr(arg)}")
|
||||||
|
|
||||||
|
if arg.is_Add and add_part is None:
|
||||||
|
add_part = arg
|
||||||
|
else:
|
||||||
|
other_parts.append(arg)
|
||||||
|
|
||||||
|
# --------------------------------------------------------
|
||||||
|
# DISTRIBUTION RULE
|
||||||
|
# --------------------------------------------------------
|
||||||
|
if add_part is not None:
|
||||||
|
print(f"expr used: {sstr(expr)}, add used: {sstr(add_part)}")
|
||||||
|
|
||||||
|
distributed_value = Mul(*other_parts)
|
||||||
|
|
||||||
|
distributed_terms = [
|
||||||
|
Mul(*other_parts, term)
|
||||||
|
for term in add_part.args
|
||||||
|
]
|
||||||
|
|
||||||
|
new_expr = build_ordered_add(distributed_terms)
|
||||||
|
|
||||||
|
return new_expr, distributed_value
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# STEP 2: PRIORITY-BASED RECURSION (IMPORTANT FIX)
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
if expr.args:
|
||||||
|
print(f"step2 args:{expr.args}")
|
||||||
|
# PASS 1: ONLY distributable Mul(Add(...))
|
||||||
|
for i, arg in enumerate(expr.args):
|
||||||
|
if arg.is_Mul and arg.has(Add):
|
||||||
|
|
||||||
|
new_arg, distributed = distribute_once(arg)
|
||||||
|
|
||||||
|
if new_arg != arg:
|
||||||
|
new_args = list(expr.args)
|
||||||
|
new_args[i] = new_arg
|
||||||
|
return build_ordered_add(new_args), distributed
|
||||||
|
|
||||||
|
# PASS 2: ONLY recurse into Add or structured nodes
|
||||||
|
for i, arg in enumerate(expr.args):
|
||||||
|
|
||||||
|
# IMPORTANT FILTER: skip pure Mul like -4*x
|
||||||
|
if arg.is_Mul and not any(a.is_Add for a in arg.args):
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_arg, distributed = distribute_once(arg)
|
||||||
|
|
||||||
|
if new_arg != arg:
|
||||||
|
new_args = list(expr.args)
|
||||||
|
new_args[i] = new_arg
|
||||||
|
return build_ordered_add(new_args), distributed
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# STEP 3: NO CHANGE
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
return expr, None
|
||||||
|
|
||||||
def clean(expr):
|
def clean(expr):
|
||||||
|
|
||||||
# remove explicit 1 multipliers
|
# remove explicit 1 multipliers
|
||||||
@@ -194,4 +511,30 @@ def clean(expr):
|
|||||||
lambda e: Mul(*[arg for arg in e.args if arg != 1])
|
lambda e: Mul(*[arg for arg in e.args if arg != 1])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def safe_format(expr):
|
||||||
|
if expr.is_Mul:
|
||||||
|
args = []
|
||||||
|
for a in expr.args:
|
||||||
|
a = safe_format(a)
|
||||||
|
if a == 1:
|
||||||
|
continue
|
||||||
|
args.append(a)
|
||||||
|
return Mul(*args, evaluate=False)
|
||||||
|
|
||||||
|
if expr.is_Add:
|
||||||
|
return expr.func(*[safe_format(a) for a in expr.args], evaluate=False)
|
||||||
|
|
||||||
|
return expr
|
||||||
|
|
||||||
|
def flatten_mul(expr):
|
||||||
|
if expr.is_Mul:
|
||||||
|
args = []
|
||||||
|
for arg in expr.args:
|
||||||
|
if arg.is_Mul:
|
||||||
|
args.extend(arg.args)
|
||||||
|
else:
|
||||||
|
args.append(arg)
|
||||||
|
return Mul(*args, evaluate=False)
|
||||||
return expr
|
return expr
|
||||||
2
main.py
2
main.py
@@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
from problem_generator import generate_problem
|
from problem_generator import generate_problem
|
||||||
from steps_generator import generate_steps
|
from steps_generator import generate_steps
|
||||||
|
from sympy import init_printing
|
||||||
|
|
||||||
#define the entry point to the programs
|
#define the entry point to the programs
|
||||||
def main():
|
def main():
|
||||||
|
init_printing(order='none')
|
||||||
problem = generate_problem()
|
problem = generate_problem()
|
||||||
steps = generate_steps(problem);
|
steps = generate_steps(problem);
|
||||||
|
|
||||||
|
|||||||
@@ -110,18 +110,24 @@ def generate_like_terms ():
|
|||||||
@register_problem_generator("quadratic")
|
@register_problem_generator("quadratic")
|
||||||
def generate_quadratic ():
|
def generate_quadratic ():
|
||||||
#ax² + bx + c = 0
|
#ax² + bx + c = 0
|
||||||
r1 = random.choice([i for i in range(-10, 16)])
|
r1 = 0
|
||||||
r2 = random.choice([i for i in range(-10, 16)])
|
r2 = 0
|
||||||
|
while r1 == 0 and r2 == 0:
|
||||||
|
r1 = random.choice(range(-10, 13))
|
||||||
|
r2 = random.choice(range(-10, 13))
|
||||||
n = random.choice([i for i in range(-5, 6) if i != 0])
|
n = random.choice([i for i in range(-5, 6) if i != 0])
|
||||||
s = random.choice([i for i in range(-5, 6) if i != 0])
|
s = random.choice([i for i in range(-5, 6) if i != 0])
|
||||||
|
|
||||||
x = symbols('x')
|
x = symbols('x')
|
||||||
expr = n *(x - r1) * (x - r2)
|
expr = n *(s * x - r1) * (x - r2)
|
||||||
|
print(f"n:{n}, s:{s}")
|
||||||
expr = expand(expr)
|
expr = expand(expr)
|
||||||
if r1 == r2:
|
root1 = Rational(r1, s)
|
||||||
solution = r1
|
root2 = Integer(r2)
|
||||||
|
if root1 == root2:
|
||||||
|
solution = sstr(root1)
|
||||||
else:
|
else:
|
||||||
solution = [r1, r2]
|
solution = [sstr(root1), sstr(root2)]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"type": "quadratic",
|
"type": "quadratic",
|
||||||
@@ -210,8 +216,14 @@ def generate_binomial ():
|
|||||||
e = a * (ans + b) + c * (ans + d)
|
e = a * (ans + b) + c * (ans + d)
|
||||||
|
|
||||||
x = symbols('x')
|
x = symbols('x')
|
||||||
left_expr = Mul(a, x + b, evaluate=False)
|
if a != 1:
|
||||||
right_expr = Mul(c, x + d, evaluate=False)
|
left_expr = Mul(a, x + b, evaluate=False)
|
||||||
|
else:
|
||||||
|
left_expr = x+b
|
||||||
|
if c != 1:
|
||||||
|
right_expr = Mul(c, x + d, evaluate=False)
|
||||||
|
else:
|
||||||
|
right_expr = x+d
|
||||||
expr = Add(left_expr, right_expr, evaluate=False)
|
expr = Add(left_expr, right_expr, evaluate=False)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -251,6 +263,6 @@ def generate_problem():
|
|||||||
|
|
||||||
problem_type = random.choices(types, weights=weights)[0]
|
problem_type = random.choices(types, weights=weights)[0]
|
||||||
template = TEMPLATES[problem_type]
|
template = TEMPLATES[problem_type]
|
||||||
return generate_like_terms()
|
return generate_binomial()
|
||||||
#return template()
|
#return template()
|
||||||
|
|
||||||
@@ -37,9 +37,11 @@ def generate_linear_steps(problem):
|
|||||||
elif b.is_positive:
|
elif b.is_positive:
|
||||||
steps.append(algebraic_steps.subtract_both_sides(current, b))
|
steps.append(algebraic_steps.subtract_both_sides(current, b))
|
||||||
current = steps[-1]["after"]
|
current = steps[-1]["after"]
|
||||||
## Second Step
|
## Second Step
|
||||||
if a != 1:
|
if a != 1 and a != -1:
|
||||||
steps.append(algebraic_steps.divide_both_sides(current, a))
|
steps.append(algebraic_steps.divide_both_sides(current, a))
|
||||||
|
elif a == -1:
|
||||||
|
steps.append(algebraic_steps.multiply_both_sides(current, a))
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
@@ -173,6 +175,7 @@ def generate_like_terms_steps (problem):
|
|||||||
#ax + bx + c = d
|
#ax + bx + c = d
|
||||||
steps = []
|
steps = []
|
||||||
|
|
||||||
|
x = symbols('x')
|
||||||
current = problem["problem"]
|
current = problem["problem"]
|
||||||
|
|
||||||
## First Step
|
## First Step
|
||||||
@@ -183,6 +186,23 @@ def generate_like_terms_steps (problem):
|
|||||||
left, right = current.split("=")
|
left, right = current.split("=")
|
||||||
left_expr = parse_expr(left)
|
left_expr = parse_expr(left)
|
||||||
b = left_expr.subs(x, 0)
|
b = left_expr.subs(x, 0)
|
||||||
|
if b.is_negative:
|
||||||
|
steps.append(algebraic_steps.add_both_sides(current, -b))
|
||||||
|
elif b.is_positive:
|
||||||
|
steps.append(algebraic_steps.subtract_both_sides(current, b))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
right_expr = parse_expr(right)
|
||||||
|
steps[-1]["after"] = f"{sstr(left_expr)} = {sstr(right_expr)}"
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
|
||||||
|
## Third Step
|
||||||
|
div = left_expr.coeff(x)
|
||||||
|
if div != 1 and div != -1:
|
||||||
|
steps.append(algebraic_steps.divide_both_sides(current, div))
|
||||||
|
elif div == -1:
|
||||||
|
steps.append(algebraic_steps.multiply_both_sides(current, div))
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
@@ -191,6 +211,38 @@ def generate_quadratic_steps (problem):
|
|||||||
#ax² + bx + c = 0
|
#ax² + bx + c = 0
|
||||||
steps = []
|
steps = []
|
||||||
|
|
||||||
|
x = symbols('x')
|
||||||
|
current = problem["problem"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
right_expr = parse_expr(right)
|
||||||
|
a = left_expr.coeff(x**2)
|
||||||
|
b = left_expr.coeff(x)
|
||||||
|
c = left_expr.subs(x, 0)
|
||||||
|
div = gcd(a, b, c)
|
||||||
|
if a.is_negative:
|
||||||
|
div = -div
|
||||||
|
|
||||||
|
## First Step
|
||||||
|
if div != 1 and c.is_zero == False:
|
||||||
|
steps.append(algebraic_steps.factor_out(current, div))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
elif c.is_zero:
|
||||||
|
div = gcd(a, b)
|
||||||
|
steps.append(algebraic_steps.factor_out(current, div*x))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
|
||||||
|
if c.is_zero == False:
|
||||||
|
## Second Steps
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
inner = left_expr / div
|
||||||
|
steps.extend(algebraic_steps.trinomial_by_grouping(current,inner))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
|
||||||
|
##Solve the Roots
|
||||||
|
steps.extend(algebraic_steps.solve_roots(current))
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
@register_steps_generator("difference_squares")
|
@register_steps_generator("difference_squares")
|
||||||
@@ -198,12 +250,37 @@ def generate_difference_squares_steps (problem):
|
|||||||
#x² - a² = 0
|
#x² - a² = 0
|
||||||
steps = []
|
steps = []
|
||||||
|
|
||||||
|
x = symbols('x')
|
||||||
|
current = problem["problem"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
b = left_expr.subs(x, 0)
|
||||||
|
|
||||||
|
## Step 1
|
||||||
|
if b.is_negative:
|
||||||
|
steps.append(algebraic_steps.add_both_sides(current, -b))
|
||||||
|
elif b.is_positive:
|
||||||
|
steps.append(algebraic_steps.subtract_both_sides(current, b))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
right_expr = parse_expr(right)
|
||||||
|
steps[-1]["after"] = f"{sstr(left_expr)} = {sstr(right_expr)}"
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
|
||||||
|
## Step 2
|
||||||
|
steps.append(algebraic_steps.square_root_both_sides(current))
|
||||||
|
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
@register_steps_generator("zero_product")
|
@register_steps_generator("zero_product")
|
||||||
def generate_zero_product_steps (problem):
|
def generate_zero_product_steps (problem):
|
||||||
#(x + a)(x + b) = 0
|
#(x + a)(x + b) = 0
|
||||||
steps = []
|
steps = []
|
||||||
|
current = problem["problem"]
|
||||||
|
|
||||||
|
steps.extend(algebraic_steps.solve_roots(current))
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
@@ -211,6 +288,28 @@ def generate_zero_product_steps (problem):
|
|||||||
def generate_radical_steps (problem):
|
def generate_radical_steps (problem):
|
||||||
#√(x + a) = b
|
#√(x + a) = b
|
||||||
steps = []
|
steps = []
|
||||||
|
x = symbols('x')
|
||||||
|
current = problem["problem"]
|
||||||
|
|
||||||
|
|
||||||
|
## First Step
|
||||||
|
steps.append(algebraic_steps.square_both_sides(current))
|
||||||
|
|
||||||
|
## Second Step
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
b = left_expr.subs(x, 0)
|
||||||
|
if b.is_zero != False:
|
||||||
|
if b.is_negative:
|
||||||
|
steps.append(algebraic_steps.add_both_sides(current, -b))
|
||||||
|
elif b.is_positive:
|
||||||
|
steps.append(algebraic_steps.subtract_both_sides(current, b))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
right_expr = parse_expr(right)
|
||||||
|
steps[-1]["after"] = f"{sstr(left_expr)} = {sstr(right_expr)}"
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
@@ -218,6 +317,31 @@ def generate_radical_steps (problem):
|
|||||||
def generate_fraction_steps (problem):
|
def generate_fraction_steps (problem):
|
||||||
#(x/a) + b = c
|
#(x/a) + b = c
|
||||||
steps = []
|
steps = []
|
||||||
|
x = symbols('x')
|
||||||
|
current = problem["problem"]
|
||||||
|
|
||||||
|
## First Step
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
b = left_expr.subs(x, 0)
|
||||||
|
if b.is_zero == False:
|
||||||
|
if b.is_negative:
|
||||||
|
steps.append(algebraic_steps.add_both_sides(current, -b))
|
||||||
|
elif b.is_positive:
|
||||||
|
steps.append(algebraic_steps.subtract_both_sides(current, b))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
left, right = current.split("=")
|
||||||
|
left_expr = parse_expr(left, transformations=transformations)
|
||||||
|
right_expr = parse_expr(right)
|
||||||
|
steps[-1]["after"] = f"{sstr(left_expr)} = {sstr(right_expr)}"
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
|
||||||
|
## Second step
|
||||||
|
num, den = fraction(left_expr)
|
||||||
|
if left_expr.subs(x,1).is_negative:
|
||||||
|
steps.append(algebraic_steps.multiply_both_sides(current, -den))
|
||||||
|
else:
|
||||||
|
steps.append(algebraic_steps.multiply_both_sides(current, den))
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
@@ -225,6 +349,17 @@ def generate_fraction_steps (problem):
|
|||||||
def generate_binomial_steps (problem):
|
def generate_binomial_steps (problem):
|
||||||
#a(x + b) + c(x + d) = e
|
#a(x + b) + c(x + d) = e
|
||||||
steps = []
|
steps = []
|
||||||
|
current = problem["problem"]
|
||||||
|
|
||||||
|
last_len = -1
|
||||||
|
while last_len != len(steps):
|
||||||
|
last_len = len(steps)
|
||||||
|
steps.extend(algebraic_steps.distribute_step(current))
|
||||||
|
if len(steps):
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
|
||||||
|
steps.append(algebraic_steps.combine_like_terms(current))
|
||||||
|
current = steps[-1]["after"]
|
||||||
|
|
||||||
return steps
|
return steps
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user