def __init__(self, **options): self.derived = True S_Structure.__init__(self, FONT_SIZE_OFFSET, SHEET_LAYOUT_UNIT, SHEET_LAYOUT, SHEET_LAYOUT_TYPE) # BEGINING OF THE ZONE TO REWRITE (see explanations below) ------------ self.header = _("Name: .......................................") self.title = \ _("Short Test: converse and contrapositive of pythagorean theorem") self.subtitle = "" self.text = "" self.answers_title = _("Examples of answers") boolean_list = [True, False] ex1 = exercise.X_RightTriangle(x_kind='short_test', x_subkind='contrapositive_of_' 'pythagorean_theorem', use_decimals=randomly.pop(boolean_list)) ex2 = exercise.X_RightTriangle(x_kind='short_test', x_subkind='converse_of_pythagorean' '_theorem', use_decimals=randomly.pop(boolean_list)) boolean_list = [True, False] ex3 = exercise.X_RightTriangle(x_kind='short_test', x_subkind='converse_of_' 'pythagorean_theorem', use_decimals=randomly.pop(boolean_list)) ex4 = exercise.X_RightTriangle(x_kind='short_test', x_subkind='contrapositive_of_' 'pythagorean_theorem', use_decimals=randomly.pop(boolean_list)) if randomly.heads_or_tails(): x_list = [ex1, ex2, ex3, ex4] else: x_list = [ex3, ex4, ex1, ex2] self.exercises_list = x_list
def __init__(self, numbers_to_use, **options): nb_list = list(numbers_to_use) hole = Item(Value('...')) self.hidden_one = None visible_one = None self.product = Item(Product([nb_list[0], nb_list[1]]).evaluate()) if isinstance(nb_list[1], Fraction): self.hidden_one = nb_list[1] visible_one = nb_list[0] else: nb1 = randomly.pop(nb_list) nb2 = randomly.pop(nb_list) nb_list = [nb1, nb2] self.hidden_one = Item(randomly.pop(nb_list)) visible_one = randomly.pop(nb_list) factors = [visible_one, hole] self.holed_product = Product([randomly.pop(factors), randomly.pop(factors)]) self.holed_product.set_compact_display(False)
def __init__(self, rank_to_use, **options): rank_to_use = rank_to_use[0] generation_type = options.get('generation_type', randomly.pop(["default", "alternative"])) figures = [str(i + 1) for i in range(9)] ranks_scale = options.get('ranks_scale', copy.copy(DEFAULT_RANKS_SCALE)) width = DEFAULT_WIDTH if 'width' in options: try: width = int(options['width']) if not (1 <= width <= len(ranks_scale)): width = DEFAULT_WIDTH except ValueError: width = DEFAULT_WIDTH if width == "random": if generation_type == "default": width = randomly.pop([3, 4, 5, 6, 7]) else: width = randomly.pop([2, 3, 4, 5], weighted_table=[0.1, 0.3, 0.35, 0.25]) if 'numberof' in options: width = randomly.pop([2, 3, 4, 5], weighted_table=[0.15, 0.4, 0.3, 0.15]) if 'numberof' in options: generation_type = "default" rank_matches_invisible_zero = False if "direct" not in options: if ('rank_matches_invisible_zero' in options and options['rank_matches_invisible_zero'] not in ["", "False"]): # __ rank_matches_invisible_zero = True self.chosen_deci = Decimal("0") # Two different ways to generate a number. Here is the "default" one: if generation_type == "default": ranks = [] if not rank_matches_invisible_zero: if 'numberof' not in options: lr = ranks_scale.index(rank_to_use) - width + 1 lowest_start_rank = lr if lr >= 0 else 0 hr = ranks_scale.index(rank_to_use) highest_start_rank = hr if hr + width < len(ranks_scale) \ else len(ranks_scale) - 1 - width highest_start_rank = highest_start_rank \ if highest_start_rank >= lowest_start_rank \ else lowest_start_rank possible_start_ranks = [ lowest_start_rank + r for r in range(highest_start_rank - lowest_start_rank + 1) ] start_rank = randomly.pop(possible_start_ranks) ranks = [start_rank + r for r in range(width)] else: ranks += [ranks_scale.index(rank_to_use)] # Probability to fill a higher rank rather than a lower one phr = 0.5 hr = lr = ranks_scale.index(rank_to_use) for i in range(width - 1): if lr == 0: phr = 1 elif hr == len(ranks_scale) - 1: phr = 0 if random.random() < phr: hr += 1 ranks += [hr] phr *= 0.4 else: lr -= 1 ranks += [lr] phr *= 2.5 else: if rank_to_use <= Decimal("0.1"): ranks = [ ranks_scale.index(r) for r in ranks_scale if r > rank_to_use ] width = min(width, len(ranks)) ranks = ranks[-width:] elif rank_to_use >= Decimal("10"): ranks = [ ranks_scale.index(r) for r in ranks_scale if r < rank_to_use ] width = min(width, len(ranks)) ranks = ranks[:width] # Let's start the generation of the number: for r in ranks: figure = randomly.pop(figures) self.chosen_deci += Decimal(figure) * ranks_scale[r] # "Alternative" way of generating a number randomly: else: figure = "0" if rank_matches_invisible_zero \ else randomly.pop(figures) self.chosen_deci += Decimal(figure) * rank_to_use ranks_scale.remove(rank_to_use) if rank_matches_invisible_zero: if rank_to_use <= Decimal("0.1"): next_rank = rank_to_use * Decimal("10") figure = randomly.pop(figures) self.chosen_deci += Decimal(figure) * next_rank ranks_scale = [r for r in ranks_scale if r > next_rank] elif rank_to_use >= Decimal("10"): next_rank = rank_to_use * Decimal("0.1") figure = randomly.pop(figures) self.chosen_deci += Decimal(figure) * next_rank ranks_scale = [r for r in ranks_scale if r < next_rank] width = min(width, len(ranks_scale)) if rank_to_use != Decimal("1") and not rank_matches_invisible_zero: figure = randomly.pop(figures) r = RANKS_CONFUSING[-(RANKS_CONFUSING.index(rank_to_use) + 1)] self.chosen_deci += Decimal(figure) * r ranks_scale.remove(r) width -= 1 for i in range(width): figure = randomly.pop(figures) r = randomly.pop(ranks_scale) self.chosen_deci += Decimal(figure) * r self.chosen_figure = (self.chosen_deci % (rank_to_use * Decimal('10'))) // rank_to_use self.chosen_deci_str = Item((self.chosen_deci)).printed self.chosen_rank = rank_to_use
def __init__(self, x_kind='default_nothing', **options): self.derived = True X_Structure.__init__(self, x_kind, AVAILABLE_X_KIND_VALUES, X_LAYOUTS, X_LAYOUT_UNIT, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options # BEGINING OF THE ZONE TO REWRITE (see explanations below) ------------ # should be default_question = question.Something default_question = question.Q_RightTriangle # TEXTS OF THE EXERCISE self.text = {'exc': "", 'ans': "" } # alternate texts section # if self.x_kind == 'short_test' \ # and self.x_subkind == 'pythagorean_theorem_one_of_each': # # __ # self.text = {'exc': "", # 'ans': _("The drawings below are only sketches.") # } # # elif self.x_kind == '...': # self.text = {'exc': "", # 'ans': "" # } # SHORT TEST & OTHER PREFORMATTED EXERCISES units = ['m', 'dm', 'cm', 'mm'] angles = randomly.pop([[0, 180], [90, 270]]) random_signs = [randomly.pop([-1, 1]), randomly.pop([-1, 1])] if self.x_kind == 'short_test': if self.x_subkind == 'pythagorean_theorem_one_of_each': q_subkinds = ['calculate_hypotenuse', 'calculate_one_leg'] if randomly.heads_or_tails(): self.questions_list.append( default_question(q_kind='pythagorean_theorem', q_subkind=randomly.pop(q_subkinds), use_pythagorean_triples=True, use_decimals=True, final_unit=randomly.pop(units), number_of_the_question='a', figure_in_the_text=False, rotate_around_barycenter=randomly .pop(angles) + random_signs[0] * randomly.integer(0, 20))) self.questions_list.append( default_question(q_kind='pythagorean_theorem', q_subkind=randomly.pop(q_subkinds), use_pythagorean_triples=False, round_to=randomly.pop([TENTH, HUNDREDTH]), final_unit=randomly.pop(units), number_of_the_question='b', figure_in_the_text=False, rotate_around_barycenter=randomly .pop(angles) + random_signs[1] * randomly.integer(0, 20))) else: self.questions_list.append( default_question(q_kind='pythagorean_theorem', q_subkind=randomly.pop(q_subkinds), use_pythagorean_triples=False, round_to=randomly.pop([TENTH, HUNDREDTH]), final_unit=randomly.pop(units), number_of_the_question='a', figure_in_the_text=False, rotate_around_barycenter=randomly .pop(angles) + random_signs[0] * randomly.integer(0, 20))) self.questions_list.append( default_question(q_kind='pythagorean_theorem', q_subkind=randomly.pop(q_subkinds), use_pythagorean_triples=True, use_decimals=True, final_unit=randomly.pop(units), number_of_the_question='b', figure_in_the_text=False, rotate_around_barycenter=randomly .pop(angles) + random_signs[1] * randomly.integer(0, 20))) elif self.x_subkind == 'converse_of_pythagorean_theorem': self.questions_list.append( default_question(q_kind='converse_of_pythagorean_theorem', q_subkind='default', use_pythagorean_triples=True, # use_decimals=randomly.heads_or_tails(), final_unit=randomly.pop(units), figure_in_the_text=False, rotate_around_barycenter=randomly .pop(angles) + random_signs[0] * randomly.integer(0, 20), **options)) elif self.x_subkind == 'contrapositive_of_pythagorean_theorem': self.questions_list.append( default_question(q_kind='contrapositive_of_' 'pythagorean_theorem', q_subkind='default', # use_decimals=randomly.heads_or_tails(), final_unit=randomly.pop(units), figure_in_the_text=False, rotate_around_barycenter=randomly .pop(angles) + random_signs[0] * randomly.integer(0, 20), **options))
def generate_values(source_id): if source_id == 'int_irreducible_frac': return [(k, Fraction((n, k))) for k in [i + 2 for i in range(18)] for n in coprime_generator(k)] elif source_id == 'rank_words': return [(elt,) for elt in RANKS] elif source_id == 'decimal_and_10_100_1000_for_multi': box_10_100_1000 = [10, 100, 1000] result = set() for n in range(20): if not box_10_100_1000: box_10_100_1000 = [10, 100, 1000] chosen_10_100_1000 = box_10_100_1000.pop() ranks_scale = list(RANKS[2:]) width = randomly.pop([1, 2, 3], weighted_table=[0.14, 0.63, 0.33]) start_rank = randomly.pop([n for n in range(len(ranks_scale))]) result |= {(chosen_10_100_1000, generate_decimal(width, ranks_scale, start_rank))} return list(result) elif source_id == 'decimal_and_10_100_1000_for_divi': box_10_100_1000 = [10, 100, 1000] result = set() for n in range(20): if not box_10_100_1000: box_10_100_1000 = [10, 100, 1000] chosen_10_100_1000 = box_10_100_1000.pop() ranks_scale = list(RANKS[2:]) width = randomly.pop([1, 2, 3], weighted_table=[0.14, 0.63, 0.33]) wt = {10: [0.2, 0.2, 0.2, 0.2, 0.2], 100: [0.25, 0.25, 0.25, 0.25, 0], 1000: [0.34, 0.33, 0.33, 0, 0]} start_rank = randomly.pop([n for n in range(len(ranks_scale))], weighted_table=wt[chosen_10_100_1000]) result |= {(chosen_10_100_1000, generate_decimal(width, ranks_scale, start_rank))} return list(result) elif source_id == 'decimal_and_one_digit_for_multi': box = [Decimal('0.1'), Decimal('0.01'), Decimal('0.001')] result = set() for n in range(20): if not box: box = [Decimal('0.1'), Decimal('0.01'), Decimal('0.001')] chosen = box.pop() ranks_scale = list() if chosen == Decimal('0.1'): ranks_scale = list(RANKS[:-1]) elif chosen == Decimal('0.01'): ranks_scale = list(RANKS[:-2]) elif chosen == Decimal('0.001'): ranks_scale = list(RANKS[:-3]) width = randomly.pop([1, 2, 3, 4], weighted_table=[0.14, 0.43, 0.33, 0.2]) start_rank = randomly.pop([n for n in range(len(ranks_scale))]) result |= {(chosen, generate_decimal(width, ranks_scale, start_rank))} return list(result) elif source_id == 'decimal_and_one_digit_for_divi': box = [Decimal('0.1'), Decimal('0.01'), Decimal('0.001')] result = set() for n in range(20): if not box: box = [Decimal('0.1'), Decimal('0.01'), Decimal('0.001')] chosen = box.pop() ranks_scale = list() if chosen == Decimal('0.1') or chosen == Decimal('0.01'): ranks_scale = list(RANKS) elif chosen == Decimal('0.001'): ranks_scale = list(RANKS[1:]) width = randomly.pop([1, 2, 3, 4], weighted_table=[0.14, 0.43, 0.33, 0.2]) start_rank = randomly.pop([n for n in range(len(ranks_scale))]) result |= {(chosen, generate_decimal(width, ranks_scale, start_rank))} return list(result) elif source_id in ['nothing', 'bypass']: return []
def __init__(self, q_kind='default_nothing', **options): self.derived = True # The call to the mother class __init__() method will set the # fields matching optional arguments which are so far: # self.q_kind, self.q_subkind # plus self.options (modified) Q_Structure.__init__(self, q_kind, AVAILABLE_Q_KIND_VALUES, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options # That's the number of the question, not of the expressions it might # contain ! self.number = "" if 'number_of_questions' in options: self.number = options['number_of_questions'] self.objct = None # 1st OPTION if q_kind == 'fraction_simplification': root = randomly.integer(2, 19, weighted_table=[ 0.225, 0.225, 0, 0.2, 0, 0.2, 0, 0, 0, 0.07, 0, 0.0375, 0, 0, 0, 0.0375, 0, 0.005 ]) factors_list = [j + 1 for j in range(10)] ten_power_factor1 = 1 ten_power_factor2 = 1 if 'with_ten_powers' in options \ and is_.a_number(options['with_ten_powers']) \ and options['with_ten_powers'] <= 1 \ and options['with_ten_powers'] >= 0: # __ if randomly.decimal_0_1() < options['with_ten_powers']: ten_powers_list = [10, 10, 100, 100] ten_power_factor1 = randomly.pop(ten_powers_list) ten_power_factor2 = randomly.pop(ten_powers_list) self.objct = Fraction( ('+', root * randomly.pop(factors_list) * ten_power_factor1, root * randomly.pop(factors_list) * ten_power_factor2)) # 2d & 3d OPTIONS # Fractions Products | Quotients elif q_kind in ['fractions_product', 'fractions_quotient']: # In some cases, the fractions will be generated # totally randomly if randomly.decimal_0_1() < 0: lil_box = [n + 2 for n in range(18)] a = randomly.pop( lil_box, weighted_table=FRACTION_PRODUCT_AND_QUOTIENT_TABLE) b = randomly.pop( lil_box, weighted_table=FRACTION_PRODUCT_AND_QUOTIENT_TABLE) lil_box = [n + 2 for n in range(18)] c = randomly.pop( lil_box, weighted_table=FRACTION_PRODUCT_AND_QUOTIENT_TABLE) d = randomly.pop( lil_box, weighted_table=FRACTION_PRODUCT_AND_QUOTIENT_TABLE) f1 = Fraction((randomly.sign(plus_signs_ratio=0.75), Item((randomly.sign(plus_signs_ratio=0.80), a)), Item( (randomly.sign(plus_signs_ratio=0.80), b)))) f2 = Fraction((randomly.sign(plus_signs_ratio=0.75), Item((randomly.sign(plus_signs_ratio=0.80), c)), Item( (randomly.sign(plus_signs_ratio=0.80), d)))) # f1 = f1.simplified() # f2 = f2.simplified() # In all other cases (80%), we'll define a "seed" a plus two # randomly numbers i and j to form the Product | Quotient: # a×i / b × c / a × j # Where b is a randomly number coprime to a×i # and c is a randomly number coprime to a×j else: a = randomly.integer(2, 8) lil_box = [i + 2 for i in range(7)] i = randomly.pop(lil_box) j = randomly.pop(lil_box) b = randomly.coprime_to(a * i, [n + 2 for n in range(15)]) c = randomly.not_coprime_to(b, [n + 2 for n in range(30)], excepted=a * j) f1 = Fraction( (randomly.sign(plus_signs_ratio=0.75), Item((randomly.sign(plus_signs_ratio=0.80), a * i)), Item((randomly.sign(plus_signs_ratio=0.80), b)))) f2 = Fraction( (randomly.sign(plus_signs_ratio=0.75), Item((randomly.sign(plus_signs_ratio=0.80), c)), Item((randomly.sign(plus_signs_ratio=0.80), a * j)))) if randomly.heads_or_tails(): f3 = f1.clone() f1 = f2.clone() f2 = f3.clone() if q_kind == 'fractions_quotient': f2 = f2.invert() if q_kind == 'fractions_product': self.objct = Product([f1, f2]) elif q_kind == 'fractions_quotient': self.objct = Quotient(('+', f1, f2, 1, 'use_divide_symbol')) # 4th OPTION # Fractions Sums elif q_kind == 'fractions_sum': randomly_position = randomly\ .integer(0, 16, weighted_table=FRACTIONS_SUMS_SCALE_TABLE) chosen_seed_and_generator = FRACTIONS_SUMS_TABLE[randomly_position] seed = randomly.integer(2, chosen_seed_and_generator[1]) # The following test is only intended to avoid having "high" # results too often. We just check if the common denominator # will be higher than 75 (arbitrary) and if yes, we redetermine # it once. We don't do it twice since we don't want to totally # forbid high denominators. if seed * chosen_seed_and_generator[0][0] \ * chosen_seed_and_generator[0][1] >= 75: # __ seed = randomly.integer(2, chosen_seed_and_generator[1]) lil_box = [0, 1] gen1 = chosen_seed_and_generator[0][lil_box.pop()] gen2 = chosen_seed_and_generator[0][lil_box.pop()] den1 = Item(gen1 * seed) den2 = Item(gen2 * seed) temp1 = randomly.integer(1, 20) temp2 = randomly.integer(1, 20) num1 = Item(temp1 // gcd(temp1, gen1 * seed)) num2 = Item(temp2 // gcd(temp2, gen2 * seed)) f1 = Fraction((randomly.sign(plus_signs_ratio=0.7), num1, den1)) f2 = Fraction((randomly.sign(plus_signs_ratio=0.7), num2, den2)) self.objct = Sum([f1.simplified(), f2.simplified()]) # 5th # still to imagine:o) # Creation of the expression: number = 0 if 'expression_number' in options \ and is_.a_natural_int(options['expression_number']): # __ number = options['expression_number'] self.expression = Expression(number, self.objct)
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_02(q_subkind, **options): max_coeff = 20 if 'max_coeff' in options and is_.an_integer(options['max_coeff']): max_coeff = options['max_coeff'] attribute_a_minus_sign = 'randomly' if 'minus_sign' in options and options['minus_sign']: attribute_a_minus_sign = 'yes' elif 'minus_sign' in options and not options['minus_sign']: attribute_a_minus_sign = 'no' # Creation of the objects # The three Monomials: ax², bx and c # Maybe we don't need to keep the integer values... a_val = randomly.integer(1, max_coeff) b_val = randomly.integer(1, max_coeff) c_val = randomly.integer(1, max_coeff) if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1', 'type_1_C1' ]: # __ c_val = randomly.integer(2, max_coeff) ax2 = Monomial((randomly.sign(), a_val, 2)) bx = Monomial((randomly.sign(), b_val, 1)) c = Monomial((randomly.sign(), c_val, 0)) # deg1: mx + p # and we need two of them deg1 = [] for i in range(2): deg1_mx = Monomial((randomly.sign(), randomly.integer(1, max_coeff), 1)) deg1_p = None if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_A1', 'type_1_B1', 'type_1_D1', 'type_1_E1', 'type_1_G1', 'type_1_H1', 'type_4_A0' ]: # __ deg1_p = Monomial( (randomly.sign(), randomly.integer(1, max_coeff), 0)) else: deg1_p = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 0)) if not deg1_p.is_null(): lil_box = [deg1_mx, deg1_p] deg1.append( Polynomial([randomly.pop(lil_box), randomly.pop(lil_box)])) else: deg1.append(deg1_mx) # deg2: mx² + px + r # and we also need two of them deg2 = [] for i in range(2): deg2_mx2 = Monomial((randomly.sign(), randomly.integer(1, max_coeff), 2)) deg2_px = None deg2_r = None if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_A1', 'type_1_B1', 'type_1_D1', 'type_1_E1', 'type_1_G1', 'type_1_H1' ]: # __ if randomly.heads_or_tails(): deg2_px = Monomial( (randomly.sign(), randomly.integer(1, max_coeff), 1)) deg2_r = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 0)) else: deg2_px = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 1)) deg2_r = Monomial( (randomly.sign(), randomly.integer(1, max_coeff), 0)) else: deg2_px = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 1)) deg2_r = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 0)) lil_box = [deg2_mx2] if not deg2_px.is_null(): lil_box.append(deg2_px) if not deg2_r.is_null(): lil_box.append(deg2_r) monomials_list_for_deg2 = [] for i in range(len(lil_box)): monomials_list_for_deg2.append(randomly.pop(lil_box)) deg2.append(Polynomial(monomials_list_for_deg2)) # Let's attribute the common factor C according to the required type # (NB: expression ± C×F1 ± C×F2) C = None if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1' ]: # __ C = c elif q_subkind in [ 'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_D1', 'type_1_E1' ]: # __ C = bx elif q_subkind in [ 'type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_G1', 'type_1_H1' ]: # __ C = ax2 elif q_subkind in [ 'type_2_A0', 'type_2_B0', 'type_2_C0', 'type_2_A1', 'type_2_B1', 'type_4_A0' ]: # __ C = Polynomial([bx, c]) elif q_subkind in [ 'type_2_D0', 'type_2_E0', 'type_2_F0', 'type_2_D1', 'type_2_E1' ]: # __ C = Polynomial([ax2, c]) elif q_subkind in [ 'type_3_A0', 'type_3_B0', 'type_3_C0', 'type_3_A1', 'type_3_B1' ]: # __ C = Polynomial([ax2, bx, c]) # Let's attribute F1 and F2 according to the required type # (NB: expression ± C×F1 ± C×F2) F1 = None F2 = None if q_subkind in [ 'type_1_A0', 'type_1_A1', 'type_1_D0', 'type_1_D1', 'type_1_G0', 'type_1_G1', 'type_2_A0', 'type_2_A1', 'type_2_D0', 'type_2_D1', 'type_3_A0', 'type_3_A1' ]: # __ F1 = deg1[0] F2 = deg1[1] elif q_subkind in [ 'type_1_B0', 'type_1_B1', 'type_1_E0', 'type_1_E1', 'type_1_H0', 'type_1_H1', 'type_2_B0', 'type_2_B1', 'type_2_E0', 'type_2_E1', 'type_3_B0', 'type_3_B1' ]: # __ F1 = deg2[0] F2 = deg2[1] elif q_subkind in [ 'type_1_C0', 'type_1_F0', 'type_1_I0', 'type_2_C0', 'type_2_F0', 'type_3_C0' ]: # __ F1 = deg1[0] F2 = deg2[0] # The special case type_4_A0: (ax+b)² + (ax+b)×deg1' # aka C² + C×F1 elif q_subkind == 'type_4_A0': F1 = C.clone() F2 = deg1[0] # Let's put a "1" somewhere in the type_*_*1 if q_subkind in [ 'type_1_A1', 'type_1_D1', 'type_1_G1', 'type_2_A1', 'type_2_D1', 'type_3_A1', 'type_1_B1', 'type_1_E1' 'type_1_H1', 'type_2_B1', 'type_2_E1', 'type_3_B1' ]: # __ if randomly.heads_or_tails(): F1 = Item(1) else: F2 = Item(1) # Let's possibly attribute a minus_sign # (NB: expression ± C×F1 ± C×F2) minus_sign = None # this will contain the name of the factor having # a supplementary minus sign in such cases: # C×F1 - C×F2# - C×F1 + C×F2 # in all the following cases, it doesn't bring anything to attribute # a minus sign if ((q_subkind in ['type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1'] and c_val < 0) or ((q_subkind in ['type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_D1', 'type_1_E1']) and b_val < 0) or ((q_subkind in ['type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_G1', 'type_1_H1']) and a_val < 0)): # __ pass # here we let minus_sign equal to None # otherwise, let's attribute one randomly, # depending on attribute_a_minus_sign else: if attribute_a_minus_sign in ['yes', 'randomly']: # __ if (attribute_a_minus_sign == 'yes' or randomly.heads_or_tails()): # __ if randomly.heads_or_tails(): minus_sign = "F1" else: minus_sign = "F2" else: pass # here we let minus_sign equal to None # Now let's build the expression ! expression = None box_product1 = [C, F1] box_product2 = [C, F2] if q_subkind == 'type_4_A0': CF1 = Product([C]) CF1.set_exponent(Value(2)) else: CF1 = Product([randomly.pop(box_product1), randomly.pop(box_product1)]) CF2 = Product([randomly.pop(box_product2), randomly.pop(box_product2)]) if minus_sign == "F1": if len(F1) >= 2: CF1 = Expandable((Item(-1), CF1)) else: CF1 = Product([Item(-1), CF1]) elif minus_sign == "F2": if len(F2) >= 2: CF2 = Expandable((Item(-1), CF2)) else: CF2 = Product([Item(-1), CF2]) expression = Sum([CF1, CF2]) # Now let's build the factorization steps ! steps = [] steps.append(expression) F1F2_sum = None if minus_sign is None: F1F2_sum = Sum([F1, F2]) elif minus_sign == "F1": if len(F1) >= 2: F1F2_sum = Sum([Expandable((Item(-1), F1)), F2]) else: F1F2_sum = Sum([Product([Item(-1), F1]), F2]) elif minus_sign == "F2": if len(F2) >= 2: F1F2_sum = Sum([F1, Expandable((Item(-1), F2))]) else: F1F2_sum = Sum([F1, Product([Item(-1), F2])]) temp = Product([C, F1F2_sum]) temp.set_compact_display(False) steps.append(temp) F1F2_sum = F1F2_sum.expand_and_reduce_next_step() while F1F2_sum is not None: steps.append(Product([C, F1F2_sum])) F1F2_sum = F1F2_sum.expand_and_reduce_next_step() # This doesn't fit the need, because too much Products are # wrongly recognized as reducible ! if steps[len(steps) - 1].is_reducible(): steps.append(steps[len(steps) - 1].reduce_()) return steps
def __init__(self, x_kind='default_nothing', **options): self.derived = True X_Structure.__init__(self, x_kind, AVAILABLE_X_KIND_VALUES, X_LAYOUTS, X_LAYOUT_UNIT, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options # BEGINING OF THE ZONE TO REWRITE ------------------------------------- default_question = question.Q_Factorization # TEXTS OF THE EXERCISE self.text = {'exc': _("Factorise: "), 'ans': ""} # alternate texts section if self.x_kind == 'level_02_easy' \ or self.x_kind == 'level_02_intermediate': self.text = {'exc': _("Factorise:"), 'ans': ""} elif (self.x_kind == 'level_03_some_not_factorizable' or (self.x_kind, self.x_subkind) == ('mini_test', 'two_factorizations')): # __ self.text = {'exc': _("Factorise, if possible:"), 'ans': ""} # SHORT TEST & OTHER PREFORMATTED EXERCISES if self.x_kind == 'short_test': if self.x_subkind == 'easy_level': # NOTE: the algebra (easy) short test uses directly one # question and passes its arguments (x_kind...) directly # to question.Factorization() (see below, at the end) pass elif self.x_subkind == 'medium_level': lil_box = [] lil_box.append( default_question(q_kind='level_01', q_subkind='ax² + bx', expression_number=0)) if randomly.heads_or_tails(): lil_box.append( default_question(q_kind='level_01', q_subkind='ax² + b', expression_number=0)) else: lil_box.append( default_question(q_kind='level_01', q_subkind='ax + b', expression_number=0)) lil_box.append( default_question(q_kind='level_01', q_subkind='not_factorizable', expression_number=0)) for i in range(len(lil_box)): q = randomly.pop(lil_box) q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) elif self.x_subkind == 'hard_level': lil_box = [] l03_kinds = [ 'sum_square_mixed', 'difference_square_mixed', randomly.pop( ['squares_difference', 'squares_difference_mixed']), randomly.pop([ 'fake_01', 'fake_01_mixed', 'fake_02', 'fake_02_mixed', 'fake_03', 'fake_03_mixed' ]), 'fake_04_any_mixed' ] for n in range(len(l03_kinds)): lil_box.append( default_question(q_kind='level_03', q_subkind=l03_kinds[n], expression_number=n + 1)) l02_kinds = [('type_2_A1', False), ('type_2_A0', True), ('type_4_A0', False)] for n in range(len(l02_kinds)): lil_box.append( default_question(q_kind='level_02', q_subkind=l02_kinds[n][0], max_coeff=10, minus_sign=l02_kinds[n][1], expression_number=n + len(l03_kinds) + 1)) for i in range(len(lil_box)): q = randomly.pop(lil_box) q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) elif self.x_kind == 'mini_test': if self.x_subkind == 'two_factorizations': lil_box = [] lil_box.append( default_question(q_kind='level_03', q_subkind=randomly.pop( ['any_fake', 'any_true'], weighted_table=[0.2, 0.8]), expression_number=1)) l02_kinds = [('type_2_A1', False), ('type_2_A0', True), ('type_4_A0', False)] n = randomly.pop([0, 1, 2]) lil_box.append( default_question(q_kind='level_02', q_subkind=l02_kinds[n][0], max_coeff=10, minus_sign=l02_kinds[n][1], expression_number=2)) for i in range(len(lil_box)): q = randomly.pop(lil_box) q.expression.name = \ alphabet.UPPERCASE[i + self.start_number] for expression in q.steps: if isinstance(expression, Expression): expression.name = \ alphabet.UPPERCASE[i + self.start_number] self.questions_list.append(q) elif self.x_kind == 'preformatted': if self.x_subkind == 'level_01_easy': # n is the number of questions still left to do n = 10 lil_box = [] lil_box.append( default_question(q_kind='level_01', q_subkind='ax² + bx', expression_number=10 - n)) n -= 1 if randomly.heads_or_tails(): lil_box.append( default_question(q_kind='level_01', q_subkind='ax² + bx', expression_number=10 - n)) n -= 1 lil_box.append( default_question(q_kind='level_01', q_subkind='ax² + b', expression_number=10 - n)) n -= 1 if randomly.heads_or_tails(): lil_box.append( default_question(q_kind='level_01', q_subkind='ax² + b', expression_number=10 - n)) n -= 1 if randomly.heads_or_tails(): lil_box.append( default_question(q_kind='level_01', q_subkind='ax² + b', expression_number=10 - n)) n -= 1 for i in range(n): lil_box.append( default_question(q_kind='level_01', q_subkind='ax + b', expression_number=n - i)) for i in range(len(lil_box)): q = randomly.pop(lil_box) q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) elif self.x_subkind == 'level_02_easy': subkinds = ['type_1_A0', 'type_1_D0', 'type_1_G0'] n1 = len(subkinds) for i in range(n1): self.questions_list.append( default_question(q_kind='level_02', q_subkind=randomly.pop(subkinds), minus_sign=False, expression_number=i)) subkinds = ['type_2_A0', 'type_2_D0'] n2 = len(subkinds) for i in range(n2): self.questions_list.append( default_question(q_kind='level_02', q_subkind=randomly.pop(subkinds), minus_sign=False, expression_number=i + n1)) elif self.x_subkind == 'level_02_intermediate': subkinds = ['type_1_D', 'type_1_G0', 'type_1_1'] n1 = len(subkinds) for i in range(n1): self.questions_list.append( default_question(q_kind='level_02', q_subkind=randomly.pop(subkinds), minus_sign=False, expression_number=i)) subkinds = randomly.pop([['type_2_A0', 'type_2_D1'], ['type_2_A1', 'type_2_D0']]) n2 = len(subkinds) for i in range(n2): self.questions_list.append( default_question(q_kind='level_02', q_subkind=randomly.pop(subkinds), minus_sign=False, expression_number=i + n1)) elif self.x_subkind == 'level_03_sum_squares': lil_box = [] for n in range(2): lil_box.append( default_question(q_kind='level_03', q_subkind='sum_square', expression_number=n + 1)) lil_box.append( default_question(q_kind='level_03', q_subkind='sum_square_mixed', expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_difference_squares': lil_box = [] for n in range(2): lil_box.append( default_question(q_kind='level_03', q_subkind='difference_square', expression_number=n + 1)) lil_box.append( default_question(q_kind='level_03', subkind='difference_square' '_mixed', expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_squares_differences': lil_box = [] for n in range(2): lil_box.append( default_question(q_kind='level_03', q_subkind='squares_difference', expression_number=n + 1)) lil_box.append( default_question(q_kind='level_03', q_subkind='squares_difference_mixed', expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_some_not_factorizable': lil_box = [] q1 = default_question(q_kind='level_03', q_subkind='any_true_mixed', expression_number=1) q2 = default_question(q_kind='level_03', q_subkind='any_fake_straight', expression_number=2) q1q2 = [q1, q2] lil_box.append(randomly.pop(q1q2)) lil_box.append(randomly.pop(q1q2)) for n in range(3): lil_box.append( default_question(q_kind='level_03', q_subkind='any_true', expression_number=n + 3)) for n in range(2): lil_box.append( default_question(q_kind='level_03', q_subkind='any_fake', expression_number=n + 5)) for n in range(2): lil_box.append( default_question(q_kind='level_03', q_subkind='any', expression_number=n + 7)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_all_kinds': all_kinds = [ 'sum_square', 'sum_square_mixed', 'difference_square', 'difference_square_mixed', 'squares_difference', 'squares_difference_mixed', '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' ] lil_box = [] for n in range(len(all_kinds)): lil_box.append( default_question(q_kind='level_03', q_subkind=all_kinds[n], expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet.UPPERCASE[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet.UPPERCASE[i] self.questions_list.append(q) # OTHER EXERCISES (BY_PASS OPTION) else: for i in range(self.q_nb): self.questions_list.append( default_question(expression_number=i + self.start_number, q_kind=self.x_subkind, **options))
def __init__(self, q_kind='default_nothing', **options): self.derived = True # The call to the mother class __init__() method will set the # fields matching optional arguments which are so far: # self.q_kind, self.q_subkind # plus self.options (modified) Q_Structure.__init__(self, q_kind, AVAILABLE_Q_KIND_VALUES, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options q_subkind = self.q_subkind # That's the number of the question, not of the expressions it might # contain ! self.number = "" steps_method = None if q_kind == 'level_01': steps_method = level_01 if q_subkind == 'mixed': q_subkind = randomly.pop( ['default', 'three_terms', 'not_factorizable']) elif q_subkind == 'mixed_factorizable': q_subkind = randomly.pop(['default', 'three_terms']) # steps = level_01(subkind) elif q_kind == 'level_02': steps_method = level_02 if q_subkind == 'default': q_subkind = 'type_123' if q_subkind == 'type_123': q_subkind = randomly.pop(['type_1', 'type_2', 'type_3']) if q_subkind == 'type_1': q_subkind = randomly.pop( ['type_1_ABC', 'type_1_DEF', 'type_1_GHI']) if q_subkind == 'type_1_ABC': q_subkind = randomly.pop(['type_1_A', 'type_1_B', 'type_1_C']) if q_subkind == 'type_1_DEF': q_subkind = randomly.pop(['type_1_D', 'type_1_E', 'type_1_F']) if q_subkind == 'type_1_GHI': q_subkind = randomly.pop(['type_1_G', 'type_1_H', 'type_1_I']) if q_subkind == 'type_1_A': q_subkind = randomly.pop(['type_1_A0', 'type_1_A1']) if q_subkind == 'type_1_B': q_subkind = randomly.pop(['type_1_B0', 'type_1_B1']) if q_subkind == 'type_1_C': q_subkind = 'type_1_C0' if q_subkind == 'type_1_D': q_subkind = randomly.pop(['type_1_D0', 'type_1_D1']) if q_subkind == 'type_1_E': q_subkind = randomly.pop(['type_1_E0', 'type_1_E1']) if q_subkind == 'type_1_F': q_subkind = 'type_1_F0' if q_subkind == 'type_1_G': q_subkind = randomly.pop(['type_1_G0', 'type_1_G1']) if q_subkind == 'type_1_H': q_subkind = randomly.pop(['type_1_H0', 'type_1_H1']) if q_subkind == 'type_1_I': q_subkind = 'type_1_I0' if q_subkind == 'type_1_0': q_subkind = randomly.pop([ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_G0', 'type_1_H0', 'type_1_I0' ]) if q_subkind == 'type_1_1': q_subkind = randomly.pop([ 'type_1_A1', 'type_1_B1', 'type_1_D1', 'type_1_E1', 'type_1_G1', 'type_1_H1' ]) if q_subkind == 'type_2': q_subkind = randomly.pop(['type_2_ABC', 'type_2_DEF']) if q_subkind == 'type_2_ABC': q_subkind = randomly.pop(['type_2_A', 'type_2_B', 'type_2_C']) if q_subkind == 'type_2_DEF': q_subkind = randomly.pop(['type_2_D', 'type_2_E', 'type_2_F']) if q_subkind == 'type_2_A': q_subkind = randomly.pop(['type_2_A0', 'type_2_A1']) if q_subkind == 'type_2_B': q_subkind = randomly.pop(['type_2_B0', 'type_2_B1']) if q_subkind == 'type_2_C': q_subkind = 'type_2_C0' if q_subkind == 'type_2_D': q_subkind = randomly.pop(['type_2_D0', 'type_2_D1']) if q_subkind == 'type_2_E': q_subkind = randomly.pop(['type_2_E0', 'type_2_E1']) if q_subkind == 'type_2_F': q_subkind = 'type_2_F0' if q_subkind == 'type_2_0': q_subkind = randomly.pop([ 'type_2_A0', 'type_2_B0', 'type_2_C0', 'type_2_D0', 'type_2_E0', 'type_2_F0' ]) if q_subkind == 'type_2_1': q_subkind = randomly.pop( ['type_2_A1', 'type_2_B1', 'type_2_D1', 'type_2_E1']) if q_subkind == 'type_3': q_subkind = 'type_3_ABC' if q_subkind == 'type_3_ABC': q_subkind = randomly.pop(['type_3_A', 'type_3_B', 'type_3_C']) if q_subkind == 'type_3_A': q_subkind = randomly.pop(['type_3_A0', 'type_3_A1']) if q_subkind == 'type_3_B': q_subkind = randomly.pop(['type_3_B0', 'type_3_B1']) if q_subkind == 'type_3_C': q_subkind = 'type_3_C0' if q_subkind == 'type_3_0': q_subkind = randomly.pop( ['type_3_A0', 'type_3_B0', 'type_3_C0']) if q_subkind == 'type_3_1': q_subkind = randomly.pop(['type_3_A1', 'type_3_B1']) # steps = level_02(subkind, **options) elif q_kind == 'level_03': steps_method = level_03 options['markup'] = shared.machine.markup if q_subkind == 'any' or q_subkind == 'default': q_subkind = randomly.pop(['any_straight', 'any_mixed']) if q_subkind == 'any_straight': q_subkind = randomly.pop( ['any_true_straight', 'any_fake_straight']) if q_subkind == 'any_mixed': q_subkind = randomly.pop(['any_true_mixed', 'any_fake_mixed']) if q_subkind == 'any_true': q_subkind = randomly.pop( ['any_true_straight', 'any_true_mixed']) if q_subkind == 'any_fake': q_subkind = randomly.pop( ['any_fake_straight', 'any_fake_mixed']) if q_subkind == 'any_true_straight': q_subkind = randomly.pop( ['sum_square', 'difference_square', 'squares_difference']) if q_subkind == 'any_fake_straight': q_subkind = randomly.pop( ['fake_01', 'fake_02', 'fake_03', 'fake_04_any_straight']) if q_subkind == 'any_true_mixed': q_subkind = randomly.pop([ 'sum_square_mixed', 'difference_square_mixed', 'squares_difference_mixed' ]) if q_subkind == 'any_fake_mixed': q_subkind = randomly.pop([ 'fake_01_mixed', 'fake_02_mixed', 'fake_03_mixed', 'fake_04_any_mixed' ]) if q_subkind == 'fake_04_any': q_subkind = randomly.pop( ['fake_04_any_mixed', 'fake_04_any_straight']) if q_subkind == 'fake_04_any_mixed': q_subkind = randomly.pop([ 'fake_04_A_mixed', 'fake_04_B_mixed', 'fake_04_C_mixed', 'fake_04_D_mixed' ]) if q_subkind == 'fake_04_any_straight': q_subkind = randomly.pop( ['fake_04_A', 'fake_04_B', 'fake_04_C', 'fake_04_D']) steps = steps_method(q_subkind, **options) # Creation of the expression: number = 0 if ('expression_number' in options and is_.a_natural_int(options['expression_number'])): # __ number = options['expression_number'] self.expression = Expression(number, steps[0]) # Putting the steps and the solution together: self.steps = [] # for i in xrange(len(steps) - 1): # self.steps.append(Expression(number, # steps[i] # ) # ) # # solution = steps[len(steps) - 1] # # if isinstance(solution, Exponented): # self.steps.append(Expression(number, # solution # ) # ) # else: # self.steps.append(solution) for i in range(len(steps)): if isinstance(steps[i], Exponented): self.steps.append(Expression(number, steps[i])) else: self.steps.append(steps[i])
def __init__(self, q_kind='default_nothing', **options): self.derived = True # The call to the mother class __init__() method will set the # fields matching optional arguments which are so far: # self.q_kind, self.q_subkind # plus self.options (modified) Q_Structure.__init__(self, q_kind, AVAILABLE_Q_KIND_VALUES, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options # Set the default values of the different options use_pythagorean_triples = False if (('use_pythagorean_triples' in options and options['use_pythagorean_triples']) or (self.q_kind == 'converse_of_pythagorean_theorem')): # __ use_pythagorean_triples = True use_decimals = True if 'use_decimals' in options and not options['use_decimals']: use_decimals = False self.round_to = "" if 'round_to' in options and options['round_to'] in PRECISION: self.round_to = options['round_to'] if not use_pythagorean_triples: if self.round_to == "": if use_decimals: self.round_to = HUNDREDTH else: self.round_to = TENTH self.use_pythagorean_triples = use_pythagorean_triples self.figure_in_the_text = True if ('figure_in_the_text' in options and not options['figure_in_the_text']): # __ self.figure_in_the_text = False rotation_option = 'no' if 'rotate_around_barycenter' in options: rotation_option = options['rotate_around_barycenter'] self.final_unit = "" if ('final_unit' in options and options['final_unit'] in LENGTH_UNITS): # __ self.final_unit = options['final_unit'] sides_units = [self.final_unit, self.final_unit, self.final_unit] # Later, allow to use a different length unit for the sides # than the final expected unit ; allow different units for different # sides (for instance giving a list in option 'sides_units')... # So far we will do with only ONE unit # if 'sides_units' in options \ # and options['sides_units'] in LENGTH_UNITS: # # __ # sides_units = options['sides_units'] self.right_triangle = None self.unknown_side = None self.known_sides = [] # Now set some randomly values letters = [elt for elt in alphabet.UPPERCASE] vertices_names = (randomly.pop(letters), randomly.pop(letters), randomly.pop(letters)) # Here you can begin to write code for the different # q_kinds & q_subkinds if self.q_kind == 'pythagorean_theorem': sides_values = [None, None, None] if use_pythagorean_triples: triples = pythagorean.ALL_TRIPLES_5_100 if use_decimals: triples = pythagorean.ALL_TRIPLES_5_100 \ + pythagorean.TRIPLES_101_200_WO_TEN_MULTIPLES sides_values = randomly.pop(triples) if use_decimals: sides_values = \ [Decimal(str(Decimal(sides_values[0]) / 10)), Decimal(str(Decimal(sides_values[1]) / 10)), Decimal(str(Decimal(sides_values[2]) / 10))] if self.q_subkind == 'calculate_hypotenuse': sides_values[2] = "" sides_units[2] = "" else: # case: self.q_subkind == 'calculate_one_leg' leg0_or_1 = randomly.pop([0, 1]) sides_values[leg0_or_1] = "" sides_units[leg0_or_1] = "" else: # NO pythagorean triples. # The two generated values must NOT match any pythagorean # triple if use_decimals: min_side_value = 5 max_side_value = 200 else: min_side_value = 5 max_side_value = 100 if self.q_subkind == 'calculate_hypotenuse': first_leg = randomly.integer(min_side_value, max_side_value) # we will take the leg values between # at least 25% and at most 150% of the length of first leg # (and smaller than max_side_value) second_leg_values = [] for i in range(int(first_leg * 1.5)): if (i + int(first_leg * 0.25) <= 1.5 * first_leg and i + int(first_leg * 0.25) <= max_side_value): # __ second_leg_values += [i + int(first_leg * 0.25)] second_leg_unauthorized_values = \ pythagorean.get_legs_matching_given_leg(first_leg) second_leg_possible_values = \ list(set(second_leg_values) - set(second_leg_unauthorized_values)) if randomly.heads_or_tails(): sides_values = \ [first_leg, randomly.pop(second_leg_possible_values), ""] sides_units[2] = "" else: sides_values = \ [randomly.pop(second_leg_possible_values), first_leg, ""] sides_units[2] = "" else: # case: self.q_subkind == 'calculate_one_leg' hypotenuse = randomly.integer(min_side_value, max_side_value) # we will take the leg values between # at least 25% and at most 90% of the length of hypotenuse # to avoid "weird" cases (with a very subtle difference # between the given values and the one to calculate) leg_values = [] for i in range(int(hypotenuse * 0.9)): if i + int(hypotenuse * 0.25) <= 0.9 * hypotenuse: leg_values += [i + int(hypotenuse * 0.25)] leg_unauthorized_values = \ pythagorean\ .get_legs_matching_given_hypotenuse(hypotenuse) leg_possible_values = list(set(leg_values) - set(leg_unauthorized_values)) if randomly.heads_or_tails(): sides_values = ["", randomly.pop(leg_possible_values), hypotenuse] sides_units[0] = "" else: sides_values = [randomly.pop(leg_possible_values), "", hypotenuse] sides_units[1] = "" self.right_triangle = \ RightTriangle((vertices_names, 'sketch'), rotate_around_isobarycenter=rotation_option) self.right_triangle.leg[0].label = Value(sides_values[0], unit=sides_units[0]) self.right_triangle.leg[1].label = Value(sides_values[1], unit=sides_units[1]) self.right_triangle.hypotenuse.label = Value(sides_values[2], unit=sides_units[2]) for side in self.right_triangle.side: if side.label.raw_value == "": self.unknown_side = side.clone() else: self.known_sides += [side.clone()] elif self.q_kind in ['converse_of_pythagorean_theorem', 'contrapositive_of_pythagorean_theorem']: # __ sides_values = [None, None, None] triples = list(pythagorean.ALL_TRIPLES_5_100) if use_decimals: triples += list(pythagorean.TRIPLES_101_200_WO_TEN_MULTIPLES) sides_values = randomly.pop(triples) if self.q_kind == 'contrapositive_of_pythagorean_theorem': # We'll change exactly one value to be sure the triplet # is NOT pythagorean if randomly.heads_or_tails(): # We will decrease the lowest value max_delta = int(0.1 * sides_values[0]) min_delta = 1 if min_delta > max_delta: max_delta = min_delta chosen_delta = randomly.pop( [i + min_delta for i in range(max_delta - min_delta + 1)]) sides_values = [sides_values[0] - chosen_delta, sides_values[1], sides_values[2]] else: # We will increase the highest value max_delta = int(0.1 * sides_values[2]) min_delta = 1 if min_delta > max_delta: max_delta = min_delta chosen_delta = randomly.pop( [i + min_delta for i in range(max_delta - min_delta + 1)]) sides_values = [sides_values[0], sides_values[1], sides_values[2] + chosen_delta] if use_decimals: sides_values = [Decimal(str(Decimal(sides_values[0]) / 10)), Decimal(str(Decimal(sides_values[1]) / 10)), Decimal(str(Decimal(sides_values[2]) / 10))] self.right_triangle = \ RightTriangle((vertices_names, 'sketch'), rotate_around_isobarycenter=rotation_option) self.right_triangle.leg[0].label = Value(sides_values[0], unit=sides_units[0]) self.right_triangle.leg[1].label = Value(sides_values[1], unit=sides_units[1]) self.right_triangle.hypotenuse.label = Value(sides_values[2], unit=sides_units[2]) self.right_triangle.right_angle.mark = ""
def text_to_str(self): PRECISION_IDIOMS = {UNIT: _("to the unit"), TENTH: _("to the tenth"), HUNDREDTH: _("to the hundreth"), THOUSANDTH: _("to the thousandth"), TEN_THOUSANDTH: _("to the ten thousandth")} M = shared.machine result = self.displayable_number if self.q_kind == 'pythagorean_theorem': if self.figure_in_the_text: result += M.insert_picture(self.right_triangle) else: result += _("The triangle {triangle_name} has a right \ angle in {right_vertex}.")\ .format(triangle_name=str(self.right_triangle.name), right_vertex=str(self.right_triangle.vertex[1] .name)) result += " " + str(self.known_sides[0].length_name) \ + " = " \ + self.known_sides[0].label.into_str(display_unit=True)\ + ". " \ + str(self.known_sides[1].length_name) \ + " = " \ + self.known_sides[1].label.into_str(display_unit=True)\ + ". " + M.write_new_line() result += _("Calculate the length of {this_side}.")\ .format(this_side=self.unknown_side.name) if self.final_unit != "": result += " " + _("Give the result in {this_unit}.")\ .format(this_unit=self.final_unit) if self.round_to != "": result += " " + _("Round the result {at_this_precision}.")\ .format(at_this_precision=PRECISION_IDIOMS[self.round_to]) elif self.q_kind in ['converse_of_pythagorean_theorem', 'contrapositive_of_pythagorean_theorem']: # __ if self.figure_in_the_text: result += M.insert_picture(self.right_triangle) else: sides_copy = [self.right_triangle.side[0].clone(), self.right_triangle.side[1].clone(), self.right_triangle.side[2].clone()] side0 = randomly.pop(sides_copy) side1 = randomly.pop(sides_copy) side2 = randomly.pop(sides_copy) result += _("{triangle_name} is a triangle such as " "{side_length0} = {nb0}, {side_length1} = {nb1} " "and {side_length2} = {nb2}")\ .format(triangle_name=str(self.right_triangle.name), side_length0=str(side0.length_name), nb0=side0.label.into_str(display_unit=True), side_length1=str(side1.length_name), nb1=side1.label.into_str(display_unit=True), side_length2=str(side2.length_name), nb2=side2.label.into_str(display_unit=True)) result += _("Is it a right triangle ? Prove your answer and if " "the triangle is right, give the name of the right " "angle.") result += M.write_new_line() return result + M.write_new_line()
def __init__(self, q_kind='default_nothing', **options): self.derived = True # The call to the mother class __init__() method will set the # fields matching optional arguments which are so far: # self.q_kind, self.q_subkind # plus self.options (modified) Q_Structure.__init__(self, q_kind, AVAILABLE_Q_KIND_VALUES, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options MAX_COEFF = MAX_COEFF_TABLE[q_kind] MAX_EXPONENT = MAX_EXPONENT_TABLE[q_kind] DEFAULT_MINIMUM_LENGTH = DEFAULT_MINIMUM_LENGTH_TABLE[q_kind] DEFAULT_MAXIMUM_LENGTH = DEFAULT_MAXIMUM_LENGTH_TABLE[q_kind] # This field is to be used in the answer_to_strs() method # to determine a possibly different algorithm for particular cases self.kind_of_answer = "" # Max coefficient & degree values... max_coeff = MAX_COEFF max_expon = MAX_EXPONENT if 'max_coeff' in options and options['max_coeff'] >= 1: max_coeff = options['max_coeff'] if 'max_expon' in options and options['max_expon'] >= 1: max_expon = options['max_expon'] length = randomly.integer(DEFAULT_MINIMUM_LENGTH, DEFAULT_MAXIMUM_LENGTH, weighted_table=[0.15, 0.25, 0.6]) if ('length' in options and is_.an_integer(options['length']) and options['length'] >= 2): # __ length = options['length'] # 1st CASE: # PRODUCT REDUCTION if q_kind == 'product': # First let's determine a pack of letters where to draw # The default one will be [a, b, c, x, y, z] # but the reduced or entire alphabets can be used as well letters_package = alphabet.abc + alphabet.xyz if 'short_test' in options and options['short_test']: # __ self.objct = Product( [Monomial((RANDOMLY, 12, 1)), Monomial((RANDOMLY, 12, 1))]) self.objct.factor[0].set_degree(1) self.objct.factor[1].set_degree(1) else: # In the case of an exercise about reducing products # in a training sheet, the answers will be more detailed self.kind_of_answer = 'product_detailed' if 'use_reduced_alphabet' in options: letters_package = alphabet.reduced elif 'use_the_entire_alphabet' in options: letters_package = alphabet.lowercase elif 'use_these_letters' in options \ and is_.a_string_list(options['use_these_letters']): # __ letters_package = options['use_these_letters'] # Maximum Items number. (We make sure at the same time that # we won't # risk to draw a greater number of letters than the available # letters # in letters_package) max_literal_items_nb = min(PR_MAX_LITERAL_ITEMS_NB, len(letters_package)) if ('max_literal_items_nb' in options and 2 <= options['max_literal_items_nb'] <= 6): # __ max_literal_items_nb = min(options['max_literal_items_nb'], len(letters_package)) # Maximum number of occurences of the same letter in # the initial expression same_letter_max_occurences = PR_SAME_LETTER_MAX_OCCURENCES_NB if ('nb_occurences_of_the_same_letter' in options and options['nb_occurences_of_the_same_letter'] >= 1): # __ same_letter_max_occurences = options['nb_occurences_of' '_the_same_letter'] # CREATION OF THE EXPRESSION # We draw randomly the letters that will appear # in the expression current_letters_package = list(letters_package) nb_of_letters_to_draw = randomly.integer( 1, max_literal_items_nb) drawn_letters = list() for j in range(nb_of_letters_to_draw): drawn_letters.append(randomly.pop(current_letters_package)) # Let's determine how many times will appear each letter # and then create a list containing each of these letters # the number of times they will appear pre_items_list = list() items_list = list() for j in range(len(drawn_letters)): if j == 0: # We make sure that at least one letter occurs twice # so that the exercise remains interesting ! # But the number of cases this letter occurs 3 three # times should be limited to keep sufficient # simple cases for the pupils to begin with. # It is really easy to make it much more complicated # simply giving: # nb_occurences_of_the_same_letter=<enough_high_nb> # as an argument. if randomly.decimal_0_1() < 0.5: occurences_nb = 2 else: occurences_nb = randomly\ .integer(2, same_letter_max_occurences) else: occurences_nb = randomly\ .integer(1, same_letter_max_occurences) if occurences_nb >= 1: for k in range(occurences_nb): pre_items_list.append(drawn_letters[j]) # draw the number of numeric Items nb_item_num = randomly.integer(1, PR_NUMERIC_ITEMS_MAX_NB) # put them in the pre items' list for j in range(nb_item_num): pre_items_list.append(NUMERIC) # prepare the items' list that will be given to the Product's # constructor loop_nb = len(pre_items_list) for j in range(loop_nb): next_item_kind = randomly.pop(pre_items_list) # It's not really useful nor really possible to limit the # number # of occurences of the same letter being drawn twice in # a row because it belongs to the exercise and there # are many cases when # the same letter is in the list in 3 over 4 elements. # if j >= 1 and next_item_kind == items_list[j - 1] # .raw_value: # pre_items_list.append(next_item_kind) # next_item_kind = randomly.pop(pre_items_list) if next_item_kind == NUMERIC: temp_item = Item((randomly.sign(plus_signs_ratio=0.75), randomly.integer(1, max_coeff), 1)) items_list.append(temp_item) else: item_value = next_item_kind temp_item = Item( (randomly.sign(plus_signs_ratio=0.9), item_value, randomly.integer(1, max_expon))) items_list.append(temp_item) # so now that the items_list is complete, # let's build the Product ! self.objct = Product(items_list) self.objct.set_compact_display(False) # Let's take some × symbols off the Product to match a more # usual situation for i in range(len(self.objct) - 1): if ((self.objct.factor[i].is_numeric() and self.objct.factor[i + 1].is_literal()) or (self.objct.factor[i].is_literal() and self.objct.factor[i + 1].is_literal() and self.objct.factor[i].raw_value != self.objct.factor[i + 1].raw_value and randomly.decimal_0_1() > 0.5)): # __ self.objct.info[i] = False # 2d CASE: # SUM OF PRODUCTS REDUCTION if q_kind == 'sum_of_products': if (not ('length' in options and is_.an_integer(options['length']) and options['length'] >= 2)): # __ length = randomly.integer(DEFAULT_MINIMUM_LENGTH, DEFAULT_MAXIMUM_LENGTH, weighted_table=[0.15, 0.25, 0.6]) # Creation of the list to give later to the Sum constructor products_list = list() for i in range(length): monomial1 = Monomial((RANDOMLY, max_coeff, max_expon)) monomial2 = Monomial((RANDOMLY, max_coeff, max_expon)) products_list.append(Product([monomial1, monomial2])) # Creation of the Sum self.objct = Sum(products_list) # 3d CASE: # SUM REDUCTION if q_kind == 'sum': self.kind_of_answer = 'sum' # Let's determine the length of the Sum to create if not ('length' in options and is_.an_integer(options['length']) and options['length'] >= 1): # __ length = randomly\ .integer(DEFAULT_MINIMUM_LENGTH, DEFAULT_MAXIMUM_LENGTH, weighted_table=[0.1, 0.25, 0.5, 0.1, 0.05]) else: length = options['length'] # Creation of the Polynomial... if 'short_test' in options: self.objct = Polynomial((RANDOMLY, max_coeff, 2, length - 1)) temp_sum = self.objct.term degree_1_monomial_here = False for i in range(len(temp_sum)): if temp_sum[i].degree == 1: degree_1_monomial_here = True if degree_1_monomial_here == 1: temp_sum.append(Monomial((randomly.sign(), 1, 1))) else: # this should be 2d deg Polynomial w/out any 1st deg term temp_sum.append(Monomial((randomly.sign(), 1, 2))) self.objct.reset_element() for i in range(length): self.objct.term.append(randomly.pop(temp_sum)) self.objct.info.append(False) else: self.objct = Polynomial( (RANDOMLY, max_coeff, max_expon, length)) if q_kind == 'long_sum': m = [] for i in range(length): m.append(Monomial(RANDOMLY, max_coeff, max_expon)) self.objct = Polynomial(m) if q_kind == 'long_sum_including_a_coeff_1': m = [] for i in range(length - 1): m.append(Monomial(RANDOMLY, max_coeff, max_expon)) m.append(Monomial(RANDOMLY, 1, max_expon)) terms_list = [] for i in range(len(m)): terms_list.append(randomly.pop(m)) self.objct = Polynomial(terms_list) if q_kind == 'sum_not_reducible': self.kind_of_answer = 'sum_not_reducible' m1 = Monomial((RANDOMLY, max_coeff, 0)) m2 = Monomial((RANDOMLY, max_coeff, 1)) m3 = Monomial((RANDOMLY, max_coeff, 2)) lil_box = [m1, m2, m3] self.objct = Polynomial([randomly.pop(lil_box)]) for i in range(len(lil_box) - 1): self.objct.append(randomly.pop(lil_box)) if q_kind == 'sum_with_minus-brackets': minus_brackets = [] for i in range(3): minus_brackets.append( Expandable((Monomial(('-', 1, 0)), Polynomial( (RANDOMLY, 15, 2, randomly.integer(2, 3)))))) m1 = Monomial((RANDOMLY, max_coeff, 0)) m2 = Monomial((RANDOMLY, max_coeff, 1)) m3 = Monomial((RANDOMLY, max_coeff, 2)) m4 = Monomial((RANDOMLY, max_coeff, randomly.integer(0, 2))) lil_box = [m1, m2, m3, m4] plus_brackets = [] for i in range(3): plus_brackets.append( Expandable((Monomial(('+', 1, 0)), Polynomial( (RANDOMLY, 15, 2, randomly.integer(2, 3)))))) big_box = [] big_box.append(minus_brackets[0]) if ('minus_brackets_nb' in options and 2 <= options['minus_brackets_nb'] <= 3): # __ big_box.append(minus_brackets[1]) if options['minus_brackets_nb'] == 3: big_box.append(minus_brackets[2]) for i in range(randomly.integer(1, 4)): big_box.append(randomly.pop(lil_box)) if ('plus_brackets_nb' in options and 1 <= options['plus_brackets_nb'] <= 3): # __ for i in range(options['plus_brackets_nb']): big_box.append(plus_brackets[i]) final_terms = [] for i in range(len(big_box)): final_terms.append(randomly.pop(big_box)) self.objct = Sum(final_terms) # Creation of the expression: number = 0 if ('expression_number' in options and is_.a_natural_int(options['expression_number'])): # __ number = options['expression_number'] self.expression = Expression(number, self.objct)
def __init__(self, x_kind='default_nothing', **options): self.derived = True X_Structure.__init__(self, x_kind, AVAILABLE_X_KIND_VALUES, X_LAYOUTS, X_LAYOUT_UNIT, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options default_question = question.Q_AlgebraExpressionExpansion # TEXTS OF THE EXERCISE self.text = {'exc': _("Expand and reduce") + ": ", 'ans': ""} # alternate texts section if self.x_subkind == 'three_numeric_binomials': self.text = { 'exc': _("Calculate thanks to a binomial " "identity:"), 'ans': "" } # PREFORMATTED EXERCISES if self.x_kind == 'short_test': if self.x_subkind == 'sign_expansion': q = default_question(q_kind='sign_expansion_short_test', expression_number=self.start_number, **options) self.questions_list.append(q) elif self.x_subkind == 'medium_level': q = default_question(q_kind='monom01_polyn1', expression_number=self.start_number, **options) self.questions_list.append(q) q = default_question(q_kind='polyn1_polyn1', expression_number=self.start_number, **options) self.questions_list.append(q) q = default_question(q_kind='sum_of_any_basic_expd', expression_number=self.start_number, **options) self.questions_list.append(q) elif self.x_subkind == 'three_binomials': kinds_list = [ 'sum_square', 'difference_square', 'squares_difference' ] for i in range(3): q = default_question(q_kind=randomly.pop(kinds_list), expression_number=i, **options) self.questions_list.append(q) elif self.x_subkind == 'three_numeric_binomials': a_list1 = [20, 30, 40, 50, 60, 70, 80, 90, 100] a_list2 = [200, 300, 400, 500, 600, 700, 800, 1000] b_list = [1, 2, 3] a1_choice = randomly.pop(a_list2) b1_choice = randomly.pop(b_list) a2_choice = randomly.pop(a_list1) b2_choice = randomly.pop(b_list) a3_choice = randomly.pop(a_list1) b3_choice = randomly.pop(b_list) a1 = Monomial(('+', a1_choice, 0)) b1 = Monomial(('+', b1_choice, 0)) a2 = Monomial(('+', a2_choice, 0)) b2 = Monomial(('+', b2_choice, 0)) a3 = Monomial(('+', a3_choice, 0)) b3 = Monomial(('+', b3_choice, 0)) kinds_list = [ 'numeric_sum_square', 'numeric_difference_square', 'numeric_squares_difference' ] monomials_to_use = [(a1, b1), (a2, b2), (a3, b3)] ordered_kinds_list = [] squares_differences_option = [0, 0, 0] for i in range(3): ordered_kinds_list.append(randomly.pop(kinds_list)) if ordered_kinds_list[i] == 'numeric_difference_square': monomials_to_use[i][1].set_sign('-') elif ordered_kinds_list[i] == 'numeric_squares_difference': squares_differences_option[i] = 1 for i in range(3): if squares_differences_option[i] == 1: q = default_question(q_kind=ordered_kinds_list[i], couple=monomials_to_use[i], squares_difference=True, expression_number=i, **options) else: q = default_question(q_kind=ordered_kinds_list[i], couple=monomials_to_use[i], expression_number=i, **options) self.questions_list.append(q) else: # default short_test option if randomly.heads_or_tails(): q1 = default_question(q_kind='monom0_polyn1', expression_number=0 + self.start_number) q2 = default_question(q_kind='monom1_polyn1', expression_number=1 + self.start_number, reversed='OK') else: q1 = default_question(q_kind='monom0_polyn1', reversed='OK', expression_number=0 + self.start_number) q2 = default_question(q_kind='monom1_polyn1', expression_number=1 + self.start_number) q3 = default_question(q_kind='polyn1_polyn1', expression_number=2 + self.start_number) self.questions_list.append(q1) self.questions_list.append(q2) self.questions_list.append(q3) elif self.x_kind == 'mini_test': if self.x_subkind == 'two_expansions_hard': if randomly.heads_or_tails(): q1 = default_question(q_kind='sum_of_any_basic_expd', q_subkind='harder', expression_number=0 + self.start_number) q2 = default_question(q_kind='sum_of_any_basic_expd', q_subkind='with_a_binomial', expression_number=1 + self.start_number) else: q1 = default_question(q_kind='sum_of_any_basic_expd', q_subkind='with_a_binomial', expression_number=0 + self.start_number) q2 = default_question(q_kind='sum_of_any_basic_expd', q_subkind='harder', expression_number=1 + self.start_number) self.questions_list.append(q1) self.questions_list.append(q2) elif self.x_subkind == 'two_randomly': if randomly.heads_or_tails(): q = default_question(q_kind='sign_expansion_short_test', expression_number=self.start_number, **options) self.questions_list.append(q) q = default_question(q_kind='polyn1_polyn1', expression_number=self.start_number + 1, **options) self.questions_list.append(q) else: q = default_question(q_kind='monom01_polyn1', expression_number=self.start_number, **options) self.questions_list.append(q) q = default_question(q_kind='sum_of_any_basic_expd', q_subkind='easy', expression_number=self.start_number + 1, **options) self.questions_list.append(q) elif self.x_kind == 'preformatted': # Mixed expandable expressions from the following types: # 0-degree Monomial × (1st-degree Polynomial) # 1-degree Monomial × (1st-degree Polynomial) # The Monomial & the polynomial may be swapped: it depends # if the option 'reversed' has been given in # argument in this method if self.x_subkind == 'mixed_monom_polyn1': choices_list = list() ratio = DEFAULT_RATIO_MIXED_MONOM_POLYN1 if 'ratio_mmp' in options \ and is_.a_number(options['ratio_mmp']) \ and options['ratio_mmp'] > 0 \ and options['ratio_mmp'] < 1: # __ ratio = options['ratio_mmp'] else: raise error.ArgumentNeeded("the ratio_mmp option " "because the " "mixed_monom_polyn1 option " "has been specified.") for i in range(int(self.q_nb * ratio) + 1): choices_list.append('monom0_polyn1') for i in range(int(self.q_nb - self.q_nb * ratio)): choices_list.append('monom1_polyn1') temp_nb = len(choices_list) for i in range(temp_nb): choice = randomly.pop(choices_list) if choice == 'monom0_polyn1': q = default_question(q_kind='monom0_polyn1', expression_number=i + self.start_number, **options) self.questions_list.append(q) else: q = default_question(q_kind='monom1_polyn1', expression_number=i + self.start_number, **options) self.questions_list.append(q) # OTHER EXERCISES else: for i in range(self.q_nb): q = default_question(q_kind=self.x_subkind, expression_number=i + self.start_number, **options) self.questions_list.append(q)
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
def __init__(self, q_kind='default_nothing', **options): self.derived = True # The call to the mother class __init__() method will set the # fields matching optional arguments which are so far: # self.q_kind, self.q_subkind # plus self.options (modified) Q_Structure.__init__(self, q_kind, AVAILABLE_Q_KIND_VALUES, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options init_caller = INIT_CALLER[q_kind] self.expandable_objct = None self.numeric_aux = None if q_kind == 'any_basic_expd': randomly_drawn = randomly.decimal_0_1() if randomly_drawn <= 0.25: self.expandable_objct = Expandable((RANDOMLY, 'monom0_polyn1'), randomly_reversed=0.5) elif randomly_drawn <= 0.50: self.expandable_objct = Expandable((RANDOMLY, 'monom1_polyn1'), randomly_reversed=0.5) else: self.expandable_objct = Expandable((RANDOMLY, 'polyn1_polyn1')) elif q_kind in ['monom0_polyn1', 'monom1_polyn1']: self.expandable_objct = Expandable((RANDOMLY, q_kind), randomly_reversed=0.5) elif q_kind == 'monom01_polyn1': self.expandable_objct = Expandable( (RANDOMLY, randomly.pop(['monom0_polyn1', 'monom1_polyn1'])), randomly_reversed=0.5) elif q_kind == 'polyn1_polyn1': self.expandable_objct = Expandable((RANDOMLY, 'polyn1_polyn1')) elif q_kind == 'sum_of_any_basic_expd': if self.q_subkind in ['harder', 'with_a_binomial']: # __ choices = ['monom0_polyn1', 'monom1_polyn1'] drawn_types = list() drawn_types.append(randomly.pop(choices)) if self.q_subkind == 'with_a_binomial': drawn_types.append('any_binomial') else: drawn_types.append('minus_polyn1_polyn1') aux_expd_list = list() for t in drawn_types: if t == 'any_binomial': aux_expd_list.append( BinomialIdentity((RANDOMLY, 'any'), **options)) else: aux_expd_list.append(Expandable((RANDOMLY, t))) final_list = list() for i in range(len(aux_expd_list)): final_list.append(randomly.pop(aux_expd_list)) self.expandable_objct = Sum(final_list) elif self.q_subkind == 'easy': choices = ['monom0_polyn1', 'monom1_polyn1'] aux_expd_list = list() aux_expd_list.append( Expandable((RANDOMLY, randomly.pop(choices)))) if randomly.heads_or_tails(): aux_expd_list.append(Expandable((RANDOMLY, 'sign_exp'))) else: aux_expd_list.append( Monomial((RANDOMLY, 15, randomly.integer(0, 2)))) final_list = list() for i in range(len(aux_expd_list)): final_list.append(randomly.pop(aux_expd_list)) self.expandable_objct = Sum(final_list) else: choices = [ 'monom0_polyn1', 'monom0_polyn1', 'monom1_polyn1', 'monom1_polyn1', 'polyn1_polyn1', 'minus_polyn1_polyn1' ] drawn_types = list() drawn_types.append(randomly.pop(choices)) drawn_types.append(randomly.pop(choices)) aux_expd_list = list() for element in drawn_types: aux_expd_list.append(Expandable((RANDOMLY, element))) aux_expd_list.append(Monomial((RANDOMLY, 15, 2))) final_list = list() for i in range(len(aux_expd_list)): final_list.append(randomly.pop(aux_expd_list)) self.expandable_objct = Sum(final_list) elif q_kind in ['sign_expansion', 'sign_expansion_short_test']: sign_exp_kind = options.get('sign_exp_kind', 0) if q_kind == 'sign_expansion_short_test': sign_exp_kind = 1 if sign_exp_kind == 0: sign_exp_kind = randomly.integer(1, 5) # Creation of the terms aux_terms_list = list() aux_expd_1 = Expandable((Monomial( (randomly.sign(), 1, 0)), Polynomial((RANDOMLY, 15, 2, 2)))) aux_expd_2 = Expandable((Monomial( (randomly.sign(), 1, 0)), Polynomial((RANDOMLY, 15, 2, 2)))) aux_expd_3 = Expandable((Monomial( (randomly.sign(), 1, 0)), Polynomial((RANDOMLY, 15, 2, 2)))) long_aux_expd = Expandable((Monomial( (randomly.sign(), 1, 0)), Polynomial((RANDOMLY, 15, 2, 3)))) if q_kind == 'sign_expansion_short_test': long_aux_expd = Expandable((Monomial( ('-', 1, 0)), Polynomial((RANDOMLY, 15, 2, 3)))) aux_monomial = Monomial((RANDOMLY, 15, 2)) # 1st kind: a Monomial and ± (long Polynomial) # (like in a short test) if sign_exp_kind == 1: aux_terms_list.append(long_aux_expd) aux_terms_list.append(aux_monomial) # 2d kind: ± (x+3) ± (4x - 7) elif sign_exp_kind == 2: aux_terms_list.append(aux_expd_1) aux_terms_list.append(aux_expd_2) # 3d kind: ± (x+3) ± (4x - 7) ± (x² - 5x) elif sign_exp_kind == 3: aux_terms_list.append(aux_expd_1) aux_terms_list.append(aux_expd_2) aux_terms_list.append(aux_expd_3) # 4th kind: ± (x+3) ± (4x - 7) ± Monomial elif sign_exp_kind == 4: aux_terms_list.append(aux_expd_1) aux_terms_list.append(aux_expd_2) aux_terms_list.append(aux_monomial) # 5th kind: ± (x+3) ± Monomial ± (long Polynomial) elif sign_exp_kind == 5: aux_terms_list.append(aux_expd_2) aux_terms_list.append(aux_monomial) aux_terms_list.append(long_aux_expd) # add as many possibilities as wanted, # don't forget to increase the last number here: # sign_exp_kind = randomly.integer(1, 5) (what's a bit above) # Now let's distribute the terms randomly final_terms_list = list() for i in range(len(aux_terms_list)): final_terms_list.append(randomly.pop(aux_terms_list)) self.expandable_objct = Sum(final_terms_list) elif q_kind in [ 'numeric_sum_square', 'numeric_difference_square', 'numeric_squares_difference' ]: # __ self.expandable_objct = init_caller( (options['couple'][0], options['couple'][1]), **options) if q_kind in ['numeric_sum_square', 'numeric_difference_square']: self.numeric_aux = Sum( [options['couple'][0], options['couple'][1]]).reduce_() self.numeric_aux.set_exponent(2) else: # squares_difference's case aux1 = Sum([options['couple'][0], options['couple'][1]]).reduce_() temp = options['couple'][1].clone() temp.set_sign('-') aux2 = Sum([options['couple'][0], temp]).reduce_() self.numeric_aux = Product([aux1, aux2]) else: if q_kind == 'any_binomial': q_kind = 'any' self.expandable_objct = init_caller((RANDOMLY, q_kind), **options) # Creation of the expression: number = 0 if 'expression_number' in options \ and is_.a_natural_int(options['expression_number']): # __ number = options['expression_number'] self.expression = Expression(number, self.expandable_objct) if self.numeric_aux is not None: self.numeric_aux = Expression(number, self.numeric_aux)
def __init__(self, x_kind='default_nothing', **options): self.derived = True X_Structure.__init__(self, x_kind, AVAILABLE_X_KIND_VALUES, X_LAYOUTS, X_LAYOUT_UNIT, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options default_question = question.Q_AlgebraExpressionReduction # TEXTS OF THE EXERCISES self.text = {'exc': _("Reduce the following expressions:"), 'ans': ""} # alternate texts section if self.x_subkind == 'product': self.text = { 'exc': _("Reduce, if possible, the following " "products:"), 'ans': _("Pay attention that the intermediate " "line is optional.") } # elif self.x_subkind == 'sum_of_products': # self.text = _("Reduce the following expressions:") elif self.x_subkind == 'sum': self.text = { 'exc': _("Reduce, if possible, the following sums:"), 'ans': _("Pay attention that the intermediate line " "is optional.") } # SHORT TEST EXERCISES if self.x_kind == 'short_test': if self.x_subkind == 'easy': self.questions_list.append( default_question(q_kind='product', short_test=True, expression_number=0)) self.questions_list.append( default_question(q_kind='sum', short_test=True, length=4, expression_number=1)) self.questions_list.append( default_question(q_kind='sum_of_products', length=2, expression_number=2)) if self.x_subkind == 'medium_level': q = [] q.append( default_question(q_kind='long_sum', expression_number=2)) q.append( default_question(q_kind='sum_not_reducible', expression_number=3)) q.append( default_question(q_kind='sum_with_minus-brackets', minus_brackets_nb=2, plus_brackets_nb=1, expression_number=4)) q.append( default_question(q_kind='long_sum_including_' 'a_coeff_1', length=7, expression_number=5)) for i in range(len(q)): self.questions_list.append(randomly.pop(q)) # PREFORMATTED EXERCISES elif self.x_kind == 'preformatted': if self.x_subkind == 'product': self.questions_list.append( default_question(q_kind='product', expression_number=0, use_these_letters=['a', 'b'], nb_occurences_of_the_same_letter=1, **options)) self.questions_list.append( default_question(q_kind='product', expression_number=1, use_these_letters=['x', 'y'], nb_occurences_of_the_same_letter=1, **options)) self.questions_list.append( default_question(q_kind='product', expression_number=2, use_these_letters=['t', 'u'], nb_occurences_of_the_same_letter=1, **options)) self.questions_list.append( default_question(q_kind='product', expression_number=3, use_these_letters=['x', 'y', 'z'], nb_occurences_of_the_same_letter=1, **options)) self.questions_list.append( default_question(q_kind='product', expression_number=4, use_these_letters=['p', 'q', 'r'], **options)) self.questions_list.append( default_question(q_kind='product', expression_number=5, use_these_letters=['a', 'b', 'x'], nb_occurences_of_the_same_letter=1, **options)) self.questions_list.append( default_question(q_kind='product', expression_number=6, use_reduced_alphabet='OK', nb_occurences_of_the_same_letter=1, **options)) self.questions_list.append( default_question(q_kind='product', expression_number=7, use_these_letters=['a', 'b', 'x'], nb_occurences_of_the_same_letter=1, **options)) self.questions_list.append( default_question(q_kind='product', expression_number=8, use_these_letters=['x', 'y'], nb_occurences_of_the_same_letter=1, **options)) # OTHER EXERCISES (BYPASS OPTION) else: for i in range(self.q_nb): self.questions_list.append( default_question(q_kind=self.x_subkind, expression_number=i + self.start_number, **options))