Пример #1
0
    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
Пример #2
0
    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)
Пример #3
0
    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
Пример #4
0
    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))
Пример #5
0
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 []
Пример #6
0
    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)
Пример #7
0
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
Пример #8
0
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
Пример #9
0
    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))
Пример #10
0
    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])
Пример #11
0
    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 = ""
Пример #12
0
    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)
Пример #15
0
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)
Пример #17
0
    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))