diff --git a/__pycache__/algebraic_steps.cpython-313.pyc b/__pycache__/algebraic_steps.cpython-313.pyc index 7cd16c3..36092b7 100644 Binary files a/__pycache__/algebraic_steps.cpython-313.pyc and b/__pycache__/algebraic_steps.cpython-313.pyc differ diff --git a/__pycache__/problem_generator.cpython-313.pyc b/__pycache__/problem_generator.cpython-313.pyc index 03e379b..fa8eaf0 100644 Binary files a/__pycache__/problem_generator.cpython-313.pyc and b/__pycache__/problem_generator.cpython-313.pyc differ diff --git a/__pycache__/steps_generator.cpython-313.pyc b/__pycache__/steps_generator.cpython-313.pyc index 00a0039..487e5f1 100644 Binary files a/__pycache__/steps_generator.cpython-313.pyc and b/__pycache__/steps_generator.cpython-313.pyc differ diff --git a/algebraic_steps.py b/algebraic_steps.py index 854b3a5..4ebb369 100644 --- a/algebraic_steps.py +++ b/algebraic_steps.py @@ -278,12 +278,10 @@ def trinomial_by_grouping(equation, inner): terms = left_expr.as_ordered_terms() t1, t2, t3, t4 = terms[0], terms[1], terms[2], terms[3] factored_part1 = factor(t1 + t2) - if t3 != -x: - div = gcd(t3, t4) - factored_part2 = factor(t3 + t4) - else: - div = -1 - factored_part2 = Mul(-1,(-t3 - t4), evaluate=False) + base = gcd(sum(terms[2:]), factored_part1) + div = simplify(sum(terms[2:]) / base) + factored_part2 = simplify((t3 + t4) / div) + factored_part2 = Mul(div,factored_part2, evaluate=False) rest = sum(terms[2:]) new_left_expr = Add(factored_part1, rest, evaluate=False) if n != 1: @@ -313,10 +311,10 @@ def trinomial_by_grouping(equation, inner): terms = left_expr.as_ordered_terms() factors = [set(t.as_ordered_factors()) for t in terms] common = set.intersection(*factors) - print(f"common:{common}, factors:{factors}, terms:{terms}, left_expr:{sstr(left_expr)}") base = list(common)[0] coeffs = [t.coeff(base) for t in terms] - new_expr = sum(coeffs) * base + #print(f"coeffs:{sstr(sum(coeffs))}, base:{sstr(base)}") + new_expr = Mul(sum(coeffs), base, evaluate=False) new_left_expr = new_expr if n != 1: new_left_expr = flatten_mul(Mul(n, new_left_expr, evaluate=False)) @@ -325,6 +323,25 @@ def trinomial_by_grouping(equation, inner): steps[-1]["step"] = f"Factor out the common factor ({sstr(base)})" steps[-1]["rule"] = "Reverse Distributive Property" + ## Flatten out identical roots optionally + if sum(coeffs) == base: + steps.append({}) + steps[-1]["before"] = steps[-2]["after"] + new_left_expr = flatten_mul(Mul(n, Mul(2, base, evaluate=False), evaluate=False)) + + steps[-1]["after"] = f"{sstr(new_left_expr)} = {sstr(right_expr)}" + steps[-1]["step"] = f"Collect the factor ({sstr(base)})" + steps[-1]["rule"] = "Collect Like Terms" + + ## multiply outer number + steps.append({}) + steps[-1]["before"] = steps[-2]["after"] + new_left_expr = flatten_mul(Mul(2*n, base, evaluate=False)) + + steps[-1]["after"] = f"{sstr(new_left_expr)} = {sstr(right_expr)}" + steps[-1]["step"] = f"Multiply Outer Numbers" + steps[-1]["rule"] = "Simplify" + return steps def solve_roots(equation): @@ -375,7 +392,7 @@ def solve_roots(equation): current = steps[-1]["after"] a = clean_factor.coeff(x) b = clean_factor.subs(x, 0) - if b.is_zero == False: + if b.is_nonzero: if b.is_negative: steps.append(add_both_sides(current, -b)) elif b.is_positive: diff --git a/main.py b/main.py index 830aa96..d286468 100644 --- a/main.py +++ b/main.py @@ -3,19 +3,35 @@ from problem_generator import generate_problem from steps_generator import generate_steps -from sympy import init_printing +from sympy import init_printing, sympify #define the entry point to the programs def main(): init_printing(order='lex') - problem = generate_problem() - steps = generate_steps(problem); + no_problem = True + test=sympify('-2') + while(no_problem): + problem = generate_problem() + steps = generate_steps(problem); + + print("Generated Problem:") + print(problem) + + print("Steps:") + pretty_print_steps(steps) + no_problem = check_solution(steps[-1]["after"], problem["solution"]) + +def check_solution(got, solution): + values = set([sympify(r.split("=")[1].strip()) for r in got.split(",")]) + if is_iterable(solution) and not isinstance(solution, str): + solutions = set([sympify(r) for r in solution]) + else: + solutions_list = [] + solutions_list.append(sympify(solution)) + solutions = set(solutions_list) + print(f"values:{values}, solutions:{solutions}") + return solutions == values - print("Generated Problem:") - print(problem) - - print("Steps:") - pretty_print_steps(steps) def pretty_print_steps(steps): print("\n" + "=" * 50) @@ -32,6 +48,13 @@ def pretty_print_steps(steps): print("\n" + "=" * 50) +def is_iterable(obj): + try: + iter(obj) + return True + except TypeError: + return False + #Starts the program if __name__ == "__main__": main() \ No newline at end of file diff --git a/problem_generator.py b/problem_generator.py index 7511930..5d8827c 100644 --- a/problem_generator.py +++ b/problem_generator.py @@ -22,7 +22,6 @@ def generate_linear(): c = a * ans + b x = symbols('x') expr = a * x + b - # expanded = n s = sstr(expr) return { @@ -137,7 +136,7 @@ def generate_quadratic (): @register_problem_generator("difference_squares") def generate_difference_squares (): #x² - a² = 0 - ans = random.choice([i for i in range(0, 13)]) + ans = random.choice([i for i in range(0, 13) if i != 0]) a = ans x = symbols('x') @@ -178,7 +177,7 @@ def generate_radical (): x = symbols('x') expr = root(x+a, 2) - + return { "type": "radical", "problem": f"{sstr(expr)} = {b}", @@ -265,6 +264,7 @@ def generate_problem(): problem_type = random.choices(types, weights=weights)[0] template = TEMPLATES[problem_type] - return generate_quadratic() - #return template() + #return list(TEMPLATES.values())[11]() + #return generate_quadratic() + return template() \ No newline at end of file diff --git a/steps_generator.py b/steps_generator.py index 782a45e..10f68d0 100644 --- a/steps_generator.py +++ b/steps_generator.py @@ -31,7 +31,7 @@ def generate_linear_steps(problem): b = expr.subs(x, 0) ## First Step - if b.is_zero == False: + if b.is_nonzero: if b.is_negative: steps.append(algebraic_steps.add_both_sides(current, -b)) elif b.is_positive: @@ -179,7 +179,7 @@ def generate_like_terms_steps (problem): current = problem["problem"] ## First Step - steps.append(algebraic_steps.combine_like_terms(current)) + steps.extend(algebraic_steps.combine_like_terms(current)) current = steps[-1]["after"] ## Second Step @@ -208,7 +208,6 @@ def generate_like_terms_steps (problem): @register_steps_generator("quadratic") def generate_quadratic_steps (problem, skip_check=False): - print(f"calling generate_quadratic_steps with: {problem["problem"]}") #ax² + bx + c = 0 steps = [] @@ -221,11 +220,13 @@ def generate_quadratic_steps (problem, skip_check=False): b = left_expr.coeff(x) c = left_expr.subs(x, 0) div = gcd(a, b, c) + if a.is_zero: + return generate_linear_steps(problem) if a.is_negative: div = -div ## First Step - if div != 1 and c.is_zero == False: + if div != 1 and c.is_nonzero: steps.append(algebraic_steps.factor_out(current, div)) current = steps[-1]["after"] elif c.is_zero: @@ -233,7 +234,7 @@ def generate_quadratic_steps (problem, skip_check=False): steps.append(algebraic_steps.factor_out(current, div*x)) current = steps[-1]["after"] - if c.is_zero == False: + if c.is_nonzero: ## Second Steps left, right = current.split("=") left_expr = parse_expr(left, transformations=transformations) @@ -253,7 +254,7 @@ def generate_quadratic_steps (problem, skip_check=False): @register_steps_generator("difference_squares") def generate_difference_squares_steps (problem, skip_check=False): - #x² - a² = 0 + #x² - a² = 0 : a is not 0 steps = [] x = symbols('x') @@ -302,15 +303,15 @@ def generate_radical_steps (problem, skip_check=False): current = problem["problem"] - ## First Step + ## Square both sides steps.append(algebraic_steps.square_both_sides(current)) - ## Second Step + ## Subtract constant 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_nonzero : if b.is_negative: steps.append(algebraic_steps.add_both_sides(current, -b)) elif b.is_positive: @@ -340,7 +341,7 @@ def generate_fraction_steps (problem): 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_nonzero: if b.is_negative: steps.append(algebraic_steps.add_both_sides(current, -b)) elif b.is_positive: @@ -386,7 +387,7 @@ def generate_binomial_steps (problem): ## Subtract constant b = left_expr.subs(x, 0) - if b.is_zero == False: + if b.is_nonzero: if b.is_negative: steps.append(algebraic_steps.add_both_sides(current, -b)) elif b.is_positive: