mathmaker  0.4(alpha)
mathmaker_dev/sheet/exercise/X_AlgebraExpressionExpansion.py
00001 # -*- coding: utf-8 -*-
00002 
00003 # Mathmaker creates automatically maths exercises sheets
00004 # with their answers
00005 # Copyright 2006-2014 Nicolas Hainaux <nico_h@users.sourceforge.net>
00006 
00007 # This file is part of Mathmaker.
00008 
00009 # Mathmaker is free software; you can redistribute it and/or modify
00010 # it under the terms of the GNU General Public License as published by
00011 # the Free Software Foundation; either version 3 of the License, or
00012 # any later version.
00013 
00014 # Mathmaker is distributed in the hope that it will be useful,
00015 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 # GNU General Public License for more details.
00018 
00019 # You should have received a copy of the GNU General Public License
00020 # along with Mathmaker; if not, write to the Free Software
00021 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023 from lib import *
00024 from X_Structure import X_Structure
00025 import question
00026 from core.base_calculus import *
00027 #from core import randomly
00028 
00029 AVAILABLE_X_KIND_VALUES = \
00030     {'short_test' : ['sign_expansion', 'medium_level',
00031                      'three_binomials', 'three_numeric_binomials',
00032                      'default'],
00033      'mini_test' : ['two_expansions_hard', 'two_randomly'],
00034      'preformatted' : ['mixed_monom_polyn1'],
00035      'bypass' : ['sign_expansion', 'any_basic_expd', 'sum_of_any_basic_expd',
00036                  'sum_square', 'difference_square', 'squares_difference',
00037                  'any_binomial', 'polyn1_polyn1', 'two_expansions_hard']
00038     }
00039 
00040 DEFAULT_RATIO_MIXED_MONOM_POLYN1 = 0.5
00041 
00042 X_LAYOUT_UNIT = "cm"
00043 # ----------------------  lines_nb    col_widths   questions
00044 X_LAYOUTS = {'default' :
00045               { 'exc' : [ None,                    'all'
00046                         ],
00047                 'ans' : [ None,                    'all'
00048                         ]
00049               },
00050 
00051              ('short_test', 'three_numeric_binomials') :
00052               { 'exc' : [ None,                    'all'
00053                         ],
00054                 'ans' : [ [1,         5.5, 5.5],   (2, 1)
00055                         ],
00056               }
00057             }
00058 
00059 # ------------------------------------------------------------------------------
00060 # --------------------------------------------------------------------------
00061 # ------------------------------------------------------------------------------
00062 ##
00063 # @class X_AlgebraExpressionExpansion
00064 # @brief Expressions to expand (like 2(x-3) or 4x(2-9x) or (3+x)(x-1))
00065 class X_AlgebraExpressionExpansion(X_Structure):
00066 
00067 
00068 
00069 
00070 
00071     # --------------------------------------------------------------------------
00072     ##
00073     #   @brief Constructor.
00074     #   @param embedded_machine The machine that will be used to write output.
00075     #   @param **options Options detailed below :
00076     #          - start_number=<integer>
00077     #                         (should be >= 1)
00078     #          - number_of_questions=<integer>
00079     #            /!\ only useful if you use x_kind and not preformatted
00080     #                         (should be >= 1)
00081     #          - x_kind=<string>
00082     #                         ...
00083     #                         ...
00084     #          - preformatted=<string>
00085     #            /!\ preformatted is useless with short_test
00086     #            /!\ number_of_questions is useless with preformatted
00087     #            /!\ if you use it with the x_kind option, ensure there's a
00088     #                preformatted possibility with this option
00089     #                         'yes'
00090     #                         'OK'
00091     #                         any other value will be understood as 'no'
00092     #          - short_test=<string>
00093     #            /!\ the x_kind option above can't be used along this option
00094     #            use subtype if you need to make different short_test exercises
00095     #                         'yes'
00096     #                         'OK'
00097     #                         any other value will be understood as 'no'
00098     #          - subtype=<string>
00099     #                         ...
00100     #                         ...
00101     #   @return One instance of exercise.AlgebraExpressionExpansion
00102     def __init__(self, embedded_machine, x_kind = 'default_nothing', **options):
00103         self.derived = True
00104         X_Structure.__init__(self, embedded_machine,
00105                              x_kind, AVAILABLE_X_KIND_VALUES, X_LAYOUTS,
00106                              X_LAYOUT_UNIT, **options)
00107         # The purpose of this next line is to get the possibly modified
00108         # value of **options
00109         options = self.options
00110 
00111         default_question = question.Q_AlgebraExpressionExpansion
00112 
00113         # TEXTS OF THE EXERCISE
00114         self.text = {'exc' : _("Expand and reduce") + " : ",
00115                      'ans' : ""
00116                     }
00117 
00118         # alternate texts section
00119         if self.x_subkind == 'three_numeric_binomials':
00120             self.text = {'exc' : \
00121                            _("Calculate thanks to a binomial identity") + " : ",
00122                          'ans' : ""
00123                         }
00124 
00125         # PREFORMATTED EXERCISES
00126         if self.x_kind == 'short_test':
00127             if self.x_subkind == 'sign_expansion':
00128                 q = default_question(self.machine,
00129                                      q_kind='sign_expansion_short_test',
00130                                      expression_number=self.start_number,
00131                                      **options)
00132 
00133                 self.questions_list.append(q)
00134 
00135             elif self.x_subkind == 'medium_level':
00136 
00137                 q = default_question(self.machine,
00138                                      q_kind='monom01_polyn1',
00139                                      expression_number=self.start_number,
00140                                      **options)
00141 
00142                 self.questions_list.append(q)
00143 
00144                 q = default_question(self.machine,
00145                                      q_kind='polyn1_polyn1',
00146                                      expression_number=self.start_number,
00147                                      **options)
00148 
00149                 self.questions_list.append(q)
00150 
00151                 q = default_question(self.machine,
00152                                      q_kind='sum_of_any_basic_expd',
00153                                      expression_number=self.start_number,
00154                                      **options)
00155 
00156                 self.questions_list.append(q)
00157 
00158 
00159 
00160 
00161             elif self.x_subkind == 'three_binomials':
00162                 kinds_list = ['sum_square',
00163                               'difference_square',
00164                               'squares_difference']
00165 
00166                 for i in xrange(3):
00167                     q = default_question(self.machine,
00168                                          q_kind=randomly.pop(kinds_list),
00169                                          expression_number=i,
00170                                          **options)
00171                     self.questions_list.append(q)
00172 
00173 
00174             elif self.x_subkind == 'three_numeric_binomials':
00175                 a_list1 = [20, 30, 40, 50, 60, 70, 80, 90, 100]
00176                 a_list2 = [200, 300, 400, 500, 600, 700, 800, 1000]
00177                 b_list = [1, 2, 3]
00178                 a1_choice = randomly.pop(a_list2)
00179                 b1_choice = randomly.pop(b_list)
00180                 a2_choice = randomly.pop(a_list1)
00181                 b2_choice = randomly.pop(b_list)
00182                 a3_choice = randomly.pop(a_list1)
00183                 b3_choice = randomly.pop(b_list)
00184 
00185                 a1 = Monomial(('+', a1_choice, 0))
00186                 b1 = Monomial(('+', b1_choice, 0))
00187                 a2 = Monomial(('+', a2_choice, 0))
00188                 b2 = Monomial(('+', b2_choice, 0))
00189                 a3 = Monomial(('+', a3_choice, 0))
00190                 b3 = Monomial(('+', b3_choice, 0))
00191 
00192                 kinds_list = ['numeric_sum_square',
00193                               'numeric_difference_square',
00194                               'numeric_squares_difference']
00195 
00196                 monomials_to_use = [(a1, b1), (a2, b2), (a3, b3)]
00197 
00198                 ordered_kinds_list = []
00199                 squares_differences_option = [0, 0, 0]
00200 
00201                 for i in xrange(3):
00202                     ordered_kinds_list.append(randomly.pop(kinds_list))
00203                     if ordered_kinds_list[i] == 'numeric_difference_square':
00204                         monomials_to_use[i][1].set_sign('-')
00205                     elif ordered_kinds_list[i] == 'numeric_squares_difference':
00206                         squares_differences_option[i] = 1
00207 
00208                 for i in xrange(3):
00209                     if squares_differences_option[i] == 1:
00210                         q = default_question(self.machine,
00211                                              q_kind=ordered_kinds_list[i],
00212                                              couple=monomials_to_use[i],
00213                                              squares_difference='yes',
00214                                              expression_number=i,
00215                                              **options)
00216                     else:
00217                         q = default_question(self.machine,
00218                                              q_kind=ordered_kinds_list[i],
00219                                              couple=monomials_to_use[i],
00220                                              expression_number=i,
00221                                              **options)
00222                     self.questions_list.append(q)
00223 
00224 
00225 
00226             else: # default short_test option
00227                 if randomly.heads_or_tails():
00228                     q1=default_question(self.machine,
00229                                         q_kind='monom0_polyn1',
00230                                         expression_number=0+self.start_number)
00231 
00232                     q2=default_question(self.machine,
00233                                         q_kind='monom1_polyn1',
00234                                         expression_number=1+self.start_number,
00235                                         reversed='OK')
00236 
00237                 else:
00238                     q1=default_question(self.machine,
00239                                         q_kind='monom0_polyn1',
00240                                         reversed='OK',
00241                                         expression_number=0+self.start_number)
00242 
00243                     q2=default_question(self.machine,
00244                                         q_kind='monom1_polyn1',
00245                                         expression_number=1+self.start_number)
00246 
00247                 q3=default_question(self.machine,
00248                                     q_kind='polyn1_polyn1',
00249                                     expression_number=2+self.start_number)
00250 
00251                 self.questions_list.append(q1)
00252                 self.questions_list.append(q2)
00253                 self.questions_list.append(q3)
00254 
00255         elif self.x_kind == 'mini_test':
00256             if self.x_subkind == 'two_expansions_hard':
00257                 if randomly.heads_or_tails():
00258                     q1=default_question(self.machine,
00259                                         q_kind='sum_of_any_basic_expd',
00260                                         q_subkind='harder',
00261                                         expression_number=0+self.start_number)
00262 
00263                     q2=default_question(self.machine,
00264                                         q_kind='sum_of_any_basic_expd',
00265                                         q_subkind='with_a_binomial',
00266                                         expression_number=1+self.start_number)
00267                 else:
00268                     q1=default_question(self.machine,
00269                                         q_kind='sum_of_any_basic_expd',
00270                                         q_subkind='with_a_binomial',
00271                                         expression_number=0+self.start_number)
00272                     q2=default_question(self.machine,
00273                                         q_kind='sum_of_any_basic_expd',
00274                                         q_subkind='harder',
00275                                         expression_number=1+self.start_number)
00276 
00277                 self.questions_list.append(q1)
00278                 self.questions_list.append(q2)
00279 
00280             elif self.x_subkind == 'two_randomly':
00281                 if randomly.heads_or_tails():
00282                     q = default_question(self.machine,
00283                                          q_kind='sign_expansion_short_test',
00284                                          expression_number=self.start_number,
00285                                          **options)
00286 
00287                     self.questions_list.append(q)
00288 
00289                     q = default_question(self.machine,
00290                                          q_kind='polyn1_polyn1',
00291                                          expression_number=self.start_number+1,
00292                                          **options)
00293 
00294                     self.questions_list.append(q)
00295 
00296                 else:
00297                     q = default_question(self.machine,
00298                                          q_kind='monom01_polyn1',
00299                                          expression_number=self.start_number,
00300                                          **options)
00301 
00302                     self.questions_list.append(q)
00303 
00304                     q = default_question(self.machine,
00305                                          q_kind='sum_of_any_basic_expd',
00306                                          q_subkind='easy',
00307                                          expression_number=self.start_number+1,
00308                                          **options)
00309 
00310                     self.questions_list.append(q)
00311 
00312         elif self.x_kind == 'preformatted':
00313             # Mixed expandable expressions from the following types :
00314             # 0-degree Monomial × (1st-degree Polynomial)
00315             # 1-degree Monomial × (1st-degree Polynomial)
00316             # The Monomial & the polynomial may be swapped : it depends
00317             # if the option 'reversed' has been given in
00318             # argument in this method
00319             if self.x_subkind == 'mixed_monom_polyn1':
00320                 choices_list = list()
00321                 ratio = DEFAULT_RATIO_MIXED_MONOM_POLYN1
00322 
00323                 if 'ratio_mmp' in options \
00324                    and is_.a_number(options['ratio_mmp']) \
00325                    and options['ratio_mmp'] > 0 \
00326                    and options['ratio_mmp'] < 1 :
00327                 #___
00328                     ratio = options['ratio_mmp']
00329                 else:
00330                     raise error.ArgumentNeeded("the ratio_mmp option " \
00331                                                + "because the " \
00332                                                + "mixed_monom_polyn1 option " \
00333                                                + "has been specified.")
00334 
00335                 for i in xrange(int(self.q_nb*ratio) + 1):
00336                     choices_list.append('monom0_polyn1')
00337                 for i in xrange(int(self.q_nb - self.q_nb*ratio)):
00338                     choices_list.append('monom1_polyn1')
00339 
00340                 temp_nb = len(choices_list)
00341 
00342                 for i in xrange(temp_nb):
00343                     choice = randomly.pop(choices_list)
00344                     if choice == 'monom0_polyn1':
00345                         q=default_question(self.machine,
00346                                          q_kind='monom0_polyn1',
00347                                          expression_number=i+self.start_number,
00348                                          **options)
00349                         self.questions_list.append(q)
00350                     else:
00351                         q=default_question(self.machine,
00352                                          q_kind='monom1_polyn1',
00353                                          expression_number=i+self.start_number,
00354                                          **options)
00355                         self.questions_list.append(q)
00356 
00357 
00358 
00359         # OTHER EXERCISES
00360         else:
00361             for i in xrange(self.q_nb):
00362                 q=default_question(self.machine,
00363                                    q_kind=self.x_subkind,
00364                                    expression_number=i+self.start_number,
00365                                    **options)
00366                 self.questions_list.append(q)
00367 
00368 
00369 
00370 
00371 
00372     # --------------------------------------------------------------------------
00373     ##
00374     #   @brief Writes the answers of the questions to the output.
00375     #def write_answer(self):
00376     #    M = self.machine
00377 
00378     #    if self.answers_text != "":
00379     #        M.write(self.answers_text)
00380     #        M.write_new_line()
00381 
00382     #    if self.x_subkind == 'three_numeric_binomials':
00383     #        M.write_tabular_begins("p{5.5 cm} p{5.5 cm}")
00384     #        self.questions_list[0].write_answer()
00385     #        M.write_new_line()
00386     #        self.questions_list[1].write_answer()
00387 
00388     #        M.write_separator_tabular_columns()
00389 
00390     #        self.questions_list[2].write_answer()
00391 
00392     #        M.write_tabular_ends()
00393 
00394     #    else: # same as in the matching structure file
00395     #        for i in xrange(len(self.questions_list)):
00396     #            self.questions_list[i].write_answer()
00397     #            M.write_new_line()
00398 
00399     #    M.write_new_line()
00400 
00401 
00402 
00403 
00404