def level_03(q_subkind, **options): a = randomly.integer(1, 10) b = randomly.integer(1, 10) steps = [] if q_subkind in [ 'sum_square', 'sum_square_mixed', 'difference_square', 'difference_square_mixed' ]: # __ first_term = Monomial(('+', Item(('+', a, 2)).evaluate(), 2)) second_term = Monomial( ('+', Item(('+', Product([2, a, b]).evaluate(), 1)).evaluate(), 1)) third_term = Monomial(('+', Item(('+', b, 2)).evaluate(), 0)) if q_subkind in ['difference_square', 'difference_square_mixed']: second_term.set_sign('-') if q_subkind in ['sum_square_mixed', 'difference_square_mixed']: ordered_expression = Polynomial( [first_term, second_term, third_term]) [first_term, second_term, third_term] = randomly.mix([first_term, second_term, third_term]) steps.append(Polynomial([first_term, second_term, third_term])) if q_subkind in ['sum_square_mixed', 'difference_square_mixed']: steps.append(ordered_expression) sq_a_monom = Monomial(('+', a, 1)) sq_b_monom = Monomial(('+', b, 0)) let_a_eq = Equality([Item('a'), sq_a_monom]) let_b_eq = Equality([Item('b'), sq_b_monom]) steps.append( _("Let") + " " + let_a_eq.into_str(force_expression_markers=True) + " " + _("and") + " " + let_b_eq.into_str(force_expression_markers=True)) sq_a_monom.set_exponent(2) sq_b_monom.set_exponent(2) a_square_eq = Equality( [Item(('+', 'a', 2)), sq_a_monom, sq_a_monom.reduce_()]) b_square_eq = Equality( [Item(('+', 'b', 2)), sq_b_monom, sq_b_monom.reduce_()]) steps.append( _("then") + " " + a_square_eq.into_str(force_expression_markers=True)) steps.append( _("and") + " " + b_square_eq.into_str(force_expression_markers=True)) two_times_a_times_b_numeric = Product( [Item(2), Monomial(('+', a, 1)), Item(b)]) two_times_a_times_b_reduced = two_times_a_times_b_numeric.reduce_() two_times_a_times_b_eq = Equality([ Product([Item(2), Item('a'), Item('b')]), two_times_a_times_b_numeric, two_times_a_times_b_reduced ]) steps.append( _("and") + " " + two_times_a_times_b_eq.into_str(force_expression_markers=True)) steps.append(_("So it is possible to factorize:")) if q_subkind in ['difference_square', 'difference_square_mixed']: b = -b factorized_expression = Sum([Monomial(('+', a, 1)), Item(b)]) factorized_expression.set_exponent(2) steps.append(factorized_expression) elif q_subkind in ['squares_difference', 'squares_difference_mixed']: # To have some (ax)² - b² but also sometimes b² - (ax)²: degrees = [2, 0, 1, 0] if randomly.integer(1, 10) >= 8: degrees = [0, 2, 0, 1] first_term = Monomial(('+', Item(('+', a, 2)).evaluate(), degrees[0])) second_term = Monomial(('-', Item(('+', b, 2)).evaluate(), degrees[1])) sq_first_term = Monomial(('+', Item( ('+', a, 1)).evaluate(), degrees[2])) sq_second_term = Monomial(('-', Item( ('+', b, 1)).evaluate(), degrees[3])) # The 'mixed' cases are: -b² + (ax)² and -(ax)² + b² if q_subkind == 'squares_difference_mixed': [first_term, second_term] = randomly.mix([first_term, second_term]) [sq_first_term, sq_second_term] = randomly.mix([sq_first_term, sq_second_term]) positive_sq_first = sq_first_term.clone() positive_sq_first.set_sign('+') positive_sq_second = sq_second_term.clone() positive_sq_second.set_sign('+') steps.append(Polynomial([first_term, second_term])) first_inter = None second_inter = None if sq_second_term.is_negative(): first_inter = positive_sq_first.clone() first_inter.set_exponent(2) temp_second_inter = positive_sq_second.clone() temp_second_inter.set_exponent(2) second_inter = Product([-1, temp_second_inter]) else: temp_first_inter = positive_sq_first.clone() temp_first_inter.set_exponent(2) first_inter = Product([-1, temp_first_inter]) second_inter = positive_sq_second.clone() second_inter.set_exponent(2) steps.append(Sum([first_inter, second_inter])) if q_subkind == 'squares_difference_mixed': steps.append(Sum([second_inter, first_inter])) steps.append(_("So, this expression can be factorized:")) sum1 = None sum2 = None if sq_second_term.is_negative(): sum1 = Sum([sq_first_term, sq_second_term]) sq_second_term.set_sign('+') sum2 = Sum([sq_first_term, sq_second_term]) else: sum1 = Sum([sq_second_term, sq_first_term]) sq_first_term.set_sign('+') sum2 = Sum([sq_second_term, sq_first_term]) lil_box = [sum1, sum2] steps.append(Product([randomly.pop(lil_box), randomly.pop(lil_box)])) elif q_subkind in [ 'fake_01', 'fake_01_mixed', 'fake_02', 'fake_02_mixed', 'fake_03', 'fake_03_mixed', 'fake_04_A', 'fake_04_A_mixed', 'fake_04_B', 'fake_04_B_mixed', 'fake_04_C', 'fake_04_C_mixed', 'fake_04_D', 'fake_04_D_mixed' ]: # __ straight_cases = [ 'fake_01', 'fake_02', 'fake_03', 'fake_04_A', 'fake_04_B', 'fake_04_C', 'fake_04_D' ] match_pb_cases = [ 'fake_01', 'fake_02', 'fake_01_mixed', 'fake_02_mixed' ] sign_pb_cases = [ 'fake_03', 'fake_03_mixed', 'fake_04_A', 'fake_04_B', 'fake_04_C', 'fake_04_D', 'fake_04_A_mixed', 'fake_04_B_mixed', 'fake_04_C_mixed', 'fake_04_D_mixed' ] ax = Monomial(('+', a, 1)) b_ = Monomial(('+', b, 0)) ax_2 = ax.clone() ax_2.set_exponent(2) a2x2 = Monomial(('+', a * a, 2)) b_2 = Monomial(('+', b, 0)) b_2.set_exponent(2) b2 = Monomial(('+', b * b, 0)) two_ax_b = Product([Item(2), Monomial(('+', a, 1)), Item(b)]) twoabx = Monomial(('+', 2 * a * b, 1)) fake_twoabx = Monomial(('+', a * b, 1)) if randomly.integer(1, 10) >= 8: fake_twoabx = Monomial( ('+', 2 * a * b + randomly.pop([-1, 1]) * randomly.integer(1, 5), 1)) first_term = None second_term = None third_term = None ordered_expression = None mixed_expression = None if q_subkind == 'fake_03' or q_subkind == 'fake_03_mixed': first_term = a2x2.clone() second_term = b2.clone() ordered_expression = Polynomial([first_term, second_term]) mixed_expression = Polynomial([second_term, first_term]) else: first_term = a2x2.clone() third_term = b2.clone() if q_subkind in [ 'fake_01', 'fake_01_mixed', 'fake_02', 'fake_02_mixed' ]: # __ second_term = fake_twoabx.clone() else: second_term = twoabx.clone() if q_subkind == 'fake_02' or q_subkind == 'fake_02_mixed': second_term.set_sign('-') elif q_subkind == 'fake_04_A' or q_subkind == 'fake_04_A_mixed': third_term.set_sign('-') elif q_subkind == 'fake_04_B' or q_subkind == 'fake_04_B_mixed': first_term.set_sign('-') elif q_subkind == 'fake_04_C' or q_subkind == 'fake_04_C_mixed': second_term.set_sign('-') third_term.set_sign('-') elif q_subkind == 'fake_04_D' or q_subkind == 'fake_04_D_mixed': first_term.set_sign('-') second_term.set_sign('-') ordered_expression = Polynomial( [first_term, second_term, third_term]) mixed_expression = Polynomial( randomly.mix([first_term, second_term, third_term])) if q_subkind in straight_cases: steps.append(ordered_expression) elif q_subkind == 'fake_03_mixed': steps.append(mixed_expression) else: steps.append(mixed_expression) steps.append(ordered_expression) if q_subkind in match_pb_cases: let_a_eq = Equality([Item('a'), ax]) let_b_eq = Equality([Item('b'), b_]) steps.append( _("Let") + " " + let_a_eq.into_str(force_expression_markers=True) + " " + _("and") + " " + let_b_eq.into_str(force_expression_markers=True)) a_square_eq = Equality([Item(('+', 'a', 2)), ax_2, a2x2]) b_square_eq = Equality([Item(('+', 'b', 2)), b_2, b2]) steps.append( _("then") + " " + a_square_eq.into_str(force_expression_markers=True)) steps.append( _("and") + " " + b_square_eq.into_str(force_expression_markers=True)) two_times_a_times_b_eq = Equality([ Product([Item(2), Item('a'), Item('b')]), two_ax_b, twoabx, fake_twoabx ], equal_signs=['=', '=', 'neq']) steps.append( _("but") + " " + two_times_a_times_b_eq.into_str(force_expression_markers=True)) steps.append(_("So it does not match a binomial identity.")) steps.append(_("This expression cannot be factorized.")) elif q_subkind in sign_pb_cases: steps.append(_("Because of the signs,")) steps.append(_("it does not match a binomial identity.")) steps.append(_("This expression cannot be factorized.")) return steps
def level_01(q_subkind, **options): if q_subkind == 'default' \ or q_subkind == 'three_terms' \ or q_subkind == 'ax + b' \ or q_subkind == 'ax² + b' \ or q_subkind == 'ax² + bx': # __ # the idea is to build the final factorized result first and to # expand it to get the question (and the solution's steps # in the same time) if q_subkind == 'default': common_factor = Monomial((RANDOMLY, 6, 1)) # In order to reduce the number of cases where x² appears, # let the common factor be of degree 0 most of the time. common_factor.set_degree( randomly.integer(0, 1, weighted_table=[0.85, 0.15])) elif q_subkind in ['three_terms', 'ax + b', 'ax² + b']: common_factor = Monomial((RANDOMLY, 6, 0)) elif q_subkind == 'ax² + bx': common_factor = Monomial((RANDOMLY, 6, 1)) common_factor.set_degree(1) # to avoid having a situation like 1×(2x + 3) which isn't # factorizable: if common_factor.get_degree() == 0: common_factor.set_coeff(randomly.integer(2, 6)) # signs are randomly chosen ; the only case that is to be avoided # is all signs are negative (then it wouldn't factorize well... # I mean then the '-' should be factorized and not left in the final # result) signs_box = [['+', '+'], ['+', '-']] signs = randomly.pop(signs_box) # this next test is to avoid -2x + 6 being factorized -2(x - 3) # which is not wrong but not "natural" to pupils # this test should be changed when a third term is being used. if signs == ['+', '-']: common_factor.set_sign('+') coeff_1 = randomly.integer(2, 10) coeff_2 = randomly.coprime_to(coeff_1, [i + 1 for i in range(10)]) coeff_3 = None if q_subkind == 'three_terms': coeff_3 = randomly.coprime_to(coeff_1 * coeff_2, [i + 1 for i in range(9)]) third_sign = randomly.sign() if third_sign == '-': common_factor.set_sign('+') signs.append(third_sign) lil_box = [] lil_box.append(Monomial(('+', 1, 0))) if q_subkind == 'ax² + b': lil_box.append(Monomial(('+', 1, 2))) else: lil_box.append(Monomial(('+', 1, 1))) if ((common_factor.get_degree() == 0 and randomly.integer(1, 20) > 17 and q_subkind == 'default') or q_subkind == 'three_terms'): # __ lil_box.append(Monomial(('+', 1, 2))) first_term = randomly.pop(lil_box) second_term = randomly.pop(lil_box) third_term = None first_term.set_coeff(coeff_1) first_term.set_sign(randomly.pop(signs)) second_term.set_coeff(coeff_2) second_term.set_sign(randomly.pop(signs)) if q_subkind == 'three_terms': third_term = randomly.pop(lil_box) third_term.set_coeff(coeff_3) third_term.set_sign(randomly.pop(signs)) if first_term.is_positive() and second_term.is_positive()\ and third_term.is_positive(): # __ common_factor.set_sign(randomly.sign()) if not (q_subkind == 'three_terms'): if common_factor.get_degree() == 0 \ and first_term.get_degree() >= 1 \ and second_term.get_degree() >= 1: # __ if randomly.heads_or_tails(): first_term.set_degree(0) else: second_term.set_degree(0) if q_subkind == 'three_terms': solution = Expandable( (common_factor, Sum([first_term, second_term, third_term]))) else: solution = Expandable( (common_factor, Sum([first_term, second_term]))) # now create the expanded step and the reduced step (which will # be given as a question) temp_steps = [] current_step = solution.clone() while current_step is not None: temp_steps.append(current_step) current_step = current_step.expand_and_reduce_next_step() # now we put the steps in the right order steps = [] for i in range(len(temp_steps)): steps.append(temp_steps[len(temp_steps) - 1 - i]) return steps elif q_subkind == 'not_factorizable': signs_box = [['+', '+'], ['+', '-']] signs = randomly.pop(signs_box) coeff_1 = randomly.integer(2, 10) coeff_2 = randomly.coprime_to(coeff_1, [i + 1 for i in range(10)]) lil_box = [] lil_box.append(Monomial(('+', 1, 0))) lil_box.append(Monomial(('+', 1, 1))) lil_box.append(Monomial(('+', 1, 2))) first_term = randomly.pop(lil_box) second_term = randomly.pop(lil_box) first_term.set_coeff(coeff_1) first_term.set_sign(randomly.pop(signs)) second_term.set_coeff(coeff_2) second_term.set_sign(randomly.pop(signs)) if first_term.get_degree() >= 1 \ and second_term.get_degree() >= 1: # __ if randomly.heads_or_tails(): first_term.set_degree(0) else: second_term.set_degree(0) steps = [] solution = _("So far, we don't know if this expression can be " "factorized.") steps.append(Sum([first_term, second_term])) steps.append(solution) return steps