def time(is_train): """Questions for calculating start, end, or time differences.""" context = composition.Context() start_minutes = random.randint(1, 24*60 - 1) while True: duration_minutes = random.randint(1, 12*60 - 1) if train_test_split.is_train(duration_minutes) == is_train: break end_minutes = start_minutes + duration_minutes def format_24hr(minutes): """Format minutes from midnight in 12 hr format.""" hours = (minutes // 60) % 24 minutes %= 60 # am_pm = 'AM' if hours < 12 else 'PM' hours = (hours - 1) % 24 + 1 return '{}:{:02}'.format(hours, minutes) start = format_24hr(start_minutes) end = format_24hr(end_minutes) which_question = random.randint(0, 3) if which_question == 0: # Question: What is start = end - duration? template = random.choice([ 'Сейчас {end}. Сколько времени было {duration} минут назад?', ]) return example.Problem( question=example.question( context, template, duration=duration_minutes, end=end), answer=start) elif which_question == 1: # Question: What is end = start + duration? template = random.choice([ 'Сейчас {start}. Сколько будет через {duration} минут?', ]) return example.Problem( question=example.question( context, template, duration=duration_minutes, start=start), answer=end) else: # Question: What is duration = end - start? template = random.choice([ 'Сколько минут между {start} и {end}?', ]) return example.Problem( question=example.question(context, template, start=start, end=end), answer=duration_minutes)
def compose(value, sample_args, context=None): """E.g., "Let f(x)=2x+1, let g(x)=3x+10. What is f(g(x))?".""" del value # unused if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() entropy_f, entropy_g = entropy * np.random.dirichlet([1, 1]) coeffs_f = polynomials.sample_coefficients([random.randint(1, 2)], entropy_f) coeffs_g = polynomials.sample_coefficients([random.randint(1, 2)], entropy_g) entity_f, entity_g = context.sample( sample_args, [composition.Polynomial(coeffs_f), composition.Polynomial(coeffs_g)]) variable = sympy.var(context.pop()) poly_f = polynomials.coefficients_to_polynomial(coeffs_f, variable) poly_g = polynomials.coefficients_to_polynomial(coeffs_g, variable) poly_f_g = poly_f.sympy().subs(variable, poly_g.sympy()).expand() expression = composition.FunctionHandle(entity_f, entity_g).apply(variable) template = random.choice(_TEMPLATES) return example.Problem(question=example.question(context, template, composed=expression), answer=poly_f_g)
def is_prime(value, sample_args, context=None): """Questions asking about primality.""" del value # unused for now if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() composite = _semi_prime(entropy) if random.choice([False, True]): # Use the composite integer = composite is_prime_ = False else: # Take the next prime after the composite, to ensure the same distribution # as composites. Do "composite - 4" so we occasionally see "2" as a prime. integer = sympy.ntheory.generate.nextprime(composite - 4) is_prime_ = True (integer_entity, ) = context.sample(sample_args, [integer]) if random.choice([False, True]) and integer != 1: answer = not is_prime_ attribute_name = random.choice(['составное', 'составное число']) else: answer = is_prime_ attribute_name = random.choice(['простое', 'простое число']) return example.Problem(question=example.question( context, '{integer} {attribute}?', integer=integer_entity.expression_else_handle, attribute=attribute_name), answer=answer)
def base_conversion(min_entropy, max_entropy): """E.g., "What is 17 base 8 in base 10?".""" context = composition.Context() from_base = random.randint(2, 16) while True: to_base = random.randint(2, 16) if to_base != from_base: break # Entropy used up in selecting bases. entropy_used = math.log10(16 * 15) entropy = random.uniform(min_entropy - entropy_used, max_entropy - entropy_used) value = number.integer(entropy, signed=True) template = random.choice([ # '{from_str} (base {from_base}) to base {to_base}', 'Приведите {from_str} (по основанию {from_base}) к основанию {to_base}.', # 'What is {from_str} (base {from_base}) in base {to_base}?', ]) return example.Problem(question=example.question( context, template, from_str=display.NumberInBase(value, from_base), from_base=from_base, to_base=to_base), answer=display.NumberInBase(value, to_base))
def nearest_integer_root(sample_args): """E.g., "Calculate the cube root of 35 to the nearest integer.".""" context = composition.Context() # With at least 50% probability, pick square or cube root (these are most # important roots!). if random.choice([False, True]): one_over_exponent = random.randint(2, 3) else: one_over_exponent = random.randint(2, 10) entropy, sample_args = sample_args.peel() value = number.integer(entropy, signed=False) answer = int(round(value ** (1 / one_over_exponent))) # templates = [ # 'What is {value} to the power of 1/{one_over_exponent}, to the nearest' # ' integer?', # ] templates = [ 'Сколько получится, если {value} возвести в степень 1/{one_over_exponent} и округлить до целого числа?', ] if one_over_exponent != 2: # "What is the second root of 4?" never used. ordinal = str() # templates += [ # 'What is the {ordinal} root of {value} to the nearest integer?', # ] templates += [ 'Чему равен {ordinal} корень от {value}? Ответ округлите до целого числа.', ] if one_over_exponent == 2: # templates += [ # 'What is the square root of {value} to the nearest integer?', # ] templates += [ 'Чему равен квадратный корень {value}? Ответ округлите до целого числа.', ] elif one_over_exponent == 3: # templates += [ # 'What is the cube root of {value} to the nearest integer?', # ] templates += [ 'Чему равен корень кубический {value}? Ответ округлите до целого числа.', ] template = random.choice(templates) ordinal = display.StringOrdinal(one_over_exponent) return example.Problem( question=example.question( context, template, value=value, ordinal=ordinal, one_over_exponent=one_over_exponent), answer=answer)
def collect(value, sample_args, context=None): """Collect terms in an unsimplified polynomial.""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: entropy_value, entropy = entropy * np.random.dirichlet([2, 3]) degrees = [random.randint(1, 3)] value = composition.Polynomial( polynomials.sample_coefficients(degrees, entropy_value)) assert isinstance(value, composition.Polynomial) coefficients = value.coefficients all_coefficients_are_integer = True for coeff in coefficients.flat: if not number.is_integer(coeff): all_coefficients_are_integer = False break if all_coefficients_are_integer: coefficients = polynomials.expand_coefficients(coefficients, entropy) else: # put back the unused entropy sample_args = composition.SampleArgs(sample_args.num_modules, sample_args.entropy + entropy) num_variables = coefficients.ndim variables = [sympy.Symbol(context.pop()) for _ in range(num_variables)] unsimplified = polynomials.coefficients_to_polynomial( coefficients, variables) simplified = unsimplified.sympy().expand() # Bit of a hack: handle the very rare case where no number constants appearing if not ops.number_constants(unsimplified): unsimplified = ops.Add(unsimplified, ops.Constant(0)) context.sample_by_replacing_constants(sample_args, unsimplified) if is_question: template = 'Упростите {unsimplified}.' return example.Problem(question=example.question( context, template, unsimplified=unsimplified), answer=simplified) else: function_symbol = context.pop() function = sympy.Function(function_symbol)(*variables) return composition.Entity( context=context, value=value, handle=composition.FunctionHandle(function_symbol), expression=unsimplified, polynomial_variables=variables, description='Пусть {function} = {unsimplified}.', function=function, unsimplified=unsimplified)
def _kth_biggest_list_question(context, entities, adjective, answer): """Ask for the biggest (or smallest, or second biggest, etc) in a list.""" entity_dict, values_template = _entities_to_list(entities) question = example.question(context, 'Какое из значений {adjective} ' + values_template + '?', adjective=adjective, **entity_dict) return example.Problem(question=question, answer=answer.handle)
def lcm(value, sample_args, context=None): """Question for least common multiple of p and q.""" del value # unused if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() p, q = _pair_with_large_hidden_factor(entropy) answer = sympy.lcm(p, q) if random.choice([False, True]): p, q = context.sample(sample_args, [p, q]) # Ask the question directly. adjective = random.choice(['наименьший']) template = random.choice([ 'Найдите {adjective} общий множитель {p} и {q}.', 'Какой {adjective} общий множитель у {p} и {q}?', ]) return example.Problem(question=example.question( context, template, adjective=adjective, p=p.expression_else_handle, q=q.expression_else_handle), answer=answer) else: # Phrase the question as finding the common denominator of two fractions. p = number.integer(2, signed=True, coprime_to=p) / p q = number.integer(2, signed=True, coprime_to=q) / q p, q = context.sample(sample_args, [p, q]) template = random.choice([ 'Найдите общий знаменатель {p} и {q}.', 'Чему равен общий знаменатель {p} и {q}?', # 'Calculate the common denominator of {p} and {q}.', ]) return example.Problem(question=example.question( context, template, p=p.expression_else_handle, q=q.expression_else_handle), answer=answer)
def _kth_biggest_multichoice_question(context, entities, adjective, answer): """Ask for the biggest (or smallest, or second biggest, etc) of choices.""" entity_dict, choices_template, answer_choice = _entities_to_choices( entities, answer) question = example.question(context, 'Какое из значений {adjective} ?' + choices_template, adjective=adjective, **entity_dict) return example.Problem(question=question, answer=answer_choice)
def add(value, sample_args, context=None): """E.g., "Let f(x)=2x+1, g(x)=3x+2. What is 5*f(x) - 7*g(x)?".""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: max_degree = 3 degree = random.randint(1, max_degree) entropy -= math.log10(max_degree) entropy_value = entropy / 2 entropy -= entropy_value value = polynomials.sample_coefficients(degree, entropy=entropy_value, min_non_zero=random.randint( 1, 3)) value = composition.Polynomial(value) c1, c2, coeffs1, coeffs2 = polynomials.coefficients_linear_split( value.coefficients, entropy) coeffs1 = polynomials.trim(coeffs1) coeffs2 = polynomials.trim(coeffs2) c1, c2, fn1, fn2 = context.sample(sample_args, [ c1, c2, composition.Polynomial(coeffs1), composition.Polynomial(coeffs2) ]) var = sympy.var(context.pop()) expression = (c1.handle * fn1.handle.apply(var) + c2.handle * fn2.handle.apply(var)) if is_question: answer = polynomials.coefficients_to_polynomial( value.coefficients, var) answer = answer.sympy() template = random.choice(_TEMPLATES) return example.Problem(question=example.question(context, template, composed=expression), answer=answer) else: intermediate_symbol = context.pop() intermediate = sympy.Function(intermediate_symbol)(var) return composition.Entity( context=context, value=value, description='Пусть {intermediate} = {composed}.', handle=composition.FunctionHandle(intermediate_symbol), intermediate=intermediate, composed=expression)
def _closest_in_list_question(context, entities, target, adjective, answer): """Ask for the closest to a given value in a list.""" entity_dict, values_template = _entities_to_list(entities) question = example.question(context, 'Что из ' + values_template + ' {adjective} к {target}?', adjective=adjective, target=target, **entity_dict) return example.Problem(question=question, answer=answer.handle)
def evaluate(value, sample_args, context=None): """Entity for evaluating an integer-valued polynomial at a given point.""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: entropy_value = random.uniform(1, 1 + entropy / 3) entropy = max(0, entropy - entropy_value) value = number.integer(entropy_value, signed=True) entropy_input = random.uniform(1, 1 + entropy / 3) entropy = max(0, entropy - entropy_input) input_ = number.integer(entropy_input, signed=True) degree = random.randint(1, 3) entropies = entropy * np.random.dirichlet(list(range(1, degree + 1))) # Calculate coefficients in reverse order. target = value coeffs_reversed = [] for i, coeff_entropy in enumerate(entropies): power = degree - i coeff = number.integer(coeff_entropy, signed=True) if input_ != 0: coeff += int(round(target / input_**power)) if coeff == 0 and i == 0: # Don't allow zero in leading coefficient. coeff += random.choice([-1, 1]) coeffs_reversed.append(coeff) target -= coeff * (input_**power) coeffs_reversed.append(target) coefficients = list(reversed(coeffs_reversed)) (polynomial_entity, input_) = context.sample(sample_args, [composition.Polynomial(coefficients), input_]) composed = polynomial_entity.handle.apply(input_.handle) if is_question: template = random.choice(_TEMPLATES) return example.Problem(question=example.question(context, template, composed=composed), answer=value) else: return composition.Entity(context=context, value=value, expression=composed, description='Пусть {self} {composed}.', composed=composed)
def _closest_multichoice_question(context, entities, target, adjective, answer): """Ask for the closest to a given value in a set of choices.""" entity_dict, choices_template, answer_choice = _entities_to_choices( entities, answer) question = example.question(context, 'Что {adjective} к {target}?' + choices_template, adjective=adjective, target=target, **entity_dict) return example.Problem(question=question, answer=answer_choice)
def _conversion_decimal(context, is_train, is_extrapolation): """E.g., "How many grams are in 5kg?".""" dimension = random.choice(DIMENSIONS) while True: base_value, base_unit, target_value, target_unit = ( _sample_conversion_decimal(dimension, is_extrapolation)) if train_test_split.is_train(base_value) == is_train: break templates = [ 'Сколько {target_name_skolko} в {base_value} {base_name_v}?', 'Переведите {base_value} {base_name_perevedi} в {target_name}.', 'Сконвертируйте {base_value} {base_name_perevedi} в {target_name}.', ] if base_unit.symbol is not None: templates += [ 'Сколько {target_name_skolko} в {base_value}{base_symbol}?', 'Переведите {base_value}{base_symbol} в {target_name}?', 'Сконвертируйте {base_value}{base_symbol} в {target_name}.', ] template = random.choice(templates) base_name = base_unit.name target_name = target_unit.name base_name_skolko = base_unit.name_skolko target_name_skolko = target_unit.name_skolko # всегда единицы для нецелых base_name_perevedi = base_unit.name_perevedi[1] base_name_v = base_unit.name_v[check_one_ending(base_value)] question = example.question( context, template, base_name=base_name, base_name_skolko=base_name_skolko, base_name_perevedi=base_name_perevedi, base_name_v=base_name_v, base_symbol=base_unit.symbol, base_value=base_value, target_name=target_name, target_name_skolko=target_name_skolko) return example.Problem(question=question, answer=target_value)
def mul(value, sample_args, context=None): """Returns random question for multiplying two numbers.""" del value # unused is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() entropy_p, entropy_q = _entropy_for_pair(entropy) p = number.integer_or_decimal(entropy_p, True) q = number.integer_or_decimal(entropy_q, True) p, q = context.sample(sample_args, [p, q]) answer = p.value * q.value if is_question: # templates = [ # '{p}' + ops.MUL_SYMBOL + '{q}', # '{p} ' + ops.MUL_SYMBOL + ' {q}', # 'Calculate {p}' + ops.MUL_SYMBOL + '{q}.', # 'Work out {p} ' + ops.MUL_SYMBOL + ' {q}.', # 'Multiply {p} and {q}.', # 'Product of {p} and {q}.', # 'What is the product of {p} and {q}?', # '{p} times {q}', # 'What is {p} times {q}?', # ] templates = [ '{p}' + ops.MUL_SYMBOL + '{q}', '{p} ' + ops.MUL_SYMBOL + ' {q}', 'Вычислите {p}' + ops.MUL_SYMBOL + '{q}.', 'Рассчитайте {p} ' + ops.MUL_SYMBOL + ' {q}.', 'Умножьте {p} и {q}.', 'Чему равно произведение {p} и {q}?', 'Умножьте {p} на {q}.', 'Сколько будет {p} умножить на {q}?', 'Каков результат произведения {p} и {q}?', ] template = random.choice(templates) return example.Problem( question=example.question(context, template, p=p, q=q), answer=answer ) else: return composition.Entity( context=context, value=answer, description='Пусть {self} = {p} * {q}.', p=p, q=q)
def coefficient_named(value, sample_args, context=None): """E.g., "Express x^2 + 2x in the form h * x^2 + k * x + t and give h.".""" del value # not used if context is None: context = composition.Context() variable = sympy.Symbol(context.pop()) entropy, sample_args = sample_args.peel() degree = random.randint(1, 4) if random.choice([False, True]): coefficients = polynomials.sample_coefficients( degree, entropy / 2, min_non_zero=random.randint(degree - 1, degree)) expanded = polynomials.expand_coefficients(coefficients, entropy / 2) expression = polynomials.coefficients_to_polynomial(expanded, variable) else: expression = polynomials.sample_with_brackets(variable, degree, entropy) coefficients = list(reversed(sympy.Poly(expression).all_coeffs())) named_coeffs = [sympy.Symbol(context.pop()) for _ in range(degree + 1)] canonical = polynomials.coefficients_to_polynomial(named_coeffs, variable) if random.random() < 0.2: # only small probability of non-zero power power = random.randint(0, degree) else: non_zero_powers = [ i for i in range(degree + 1) if coefficients[i] != 0 ] power = random.choice(non_zero_powers) value = coefficients[power] named_coeff = named_coeffs[power] template = random.choice([ 'Выразите {expression} в форме {canonical} и найдите {target}.', 'Преобразуйте {expression} в форму {canonical} и найдите {target}.', # 'Express {expression} in the form {canonical} and give {target}.', # 'Rearrange {expression} to the form {canonical} and give {target}.', ]) return example.Problem(question=example.question(context, template, expression=expression, canonical=canonical, target=named_coeff), answer=value)
def sort(sample_args, count=None): """Ask to sort numbers in increasing or decreasing order.""" sample_args = sample_args() context = composition.Context() entropy, sample_args = sample_args.peel() # Sometimes just integers, to allow for more terms in a short space. values = _unique_values(entropy, only_integers=random.choice([False, True]), count=count) entities = context.sample(sample_args, values) unsorted_dict, unsorted_template = _entities_to_list(entities) ascending = random.choice([False, True]) templates = [ 'Отсортируйте ' + unsorted_template + ' {direction}.', 'Расположите ' + unsorted_template + ' {direction}.', ] if ascending: direction = random.choice([ 'по возрастанию', 'в порядке возрастания', ]) else: direction = random.choice([ 'по убыванию', 'в порядке убывания', ]) template = random.choice(templates) sorted_entities = sorted(entities, key=_entity_sort_key, reverse=(not ascending)) answer = '' for i, entity in enumerate(sorted_entities): if i > 0: answer += ', ' answer += str(entity.handle) return example.Problem(question=example.question(context, template, direction=direction, **unsorted_dict), answer=answer)
def place_value(value, sample_args, context=None): """E.g., "Q: What is the tens digit of 31859? A: 5.""" del value # unused for now if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() integer = number.integer(entropy, signed=False, min_abs=1) (entity, ) = context.sample(sample_args, [integer]) integer_as_string = str(integer) num_digits = len(integer_as_string) firsts = ['', 'десятков ', 'сотен '] seconds = [ 'тысяч', 'миллионов', 'миллиардов', 'триллионов', 'квадриллионов', 'квинтиллионов', 'секстиллионов', 'септиллионов', 'октиллионов', 'нониллионов', 'дециллионов', ] place_names = ['единиц', 'десятков', 'сотен'] for second in seconds: for first in firsts: place_names.append(first + second) place = random.randint(1, num_digits) # 1 = units, 2 = tens, etc. place_name = place_names[place - 1] answer = sympy.Integer(integer_as_string[num_digits - place]) return example.Problem(question=example.question( context, np.random.choice([ 'Какая цифра в числе {integer} соответствует разряду {place_name}.', 'Какая цифра стоит в разряде {place_name} в числе {integer}?', ]), place_name=place_name, integer=entity.expression_else_handle), answer=answer)
def _calculate(value, sample_args, context, add_sub, mul_div, length=None): """Questions for evaluating arithmetic expressions.""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value in [_INT, _INT_OR_RATIONAL]: value_entropy = max(1.0, entropy / 4) entropy = max(1.0, entropy - value_entropy) sampler = _value_sampler(value) value = sampler(value_entropy) op = arithmetic.arithmetic( value=value, entropy=entropy, add_sub=add_sub, mul_div=mul_div, length=length) context.sample_by_replacing_constants(sample_args, op) if is_question: # template = random.choice([ # '{op}', # 'What is {op}?', # 'Evaluate {op}.', # 'Calculate {op}.', # 'What is the value of {op}?', # ]) template = random.choice([ # '{op}', 'Чему равно {op}?', 'Решите {op}.', 'Вычислите {op}.', # 'What is the value of {op}?', ]) return example.Problem( question=example.question(context, template, op=op), answer=value) else: return composition.Entity( context=context, value=value, expression=op, description='Пусть {self} равняется {op}.', op=op)
def expand(value, sample_args, context=None): """E.g., "Expand (x**2 + 1)**2.".""" del value # not used if context is None: context = composition.Context() variable = sympy.Symbol(context.pop()) entropy, sample_args = sample_args.peel() min_order = 1 max_order = 5 order = random.randint(min_order, max_order) entropy -= math.log10(max_order - min_order + 1) expression_ = polynomials.sample_with_brackets(variable, order, entropy) expanded = sympy.expand(expression_) template = random.choice(['Раскройте скобки {expression}.']) return example.Problem(question=example.question(context, template, expression=expression_), answer=expanded)
def gcd(value, sample_args, context=None): """Question for greatest common divisor of p and q.""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: value_entropy = 1 + random.uniform(0, entropy / 3) entropy = max(1, entropy - value_entropy) value = number.integer(value_entropy, False, min_abs=1) p_mult, q_mult = _random_coprime_pair(entropy) p = value * p_mult q = value * q_mult assert sympy.gcd(p, q) == value p, q = context.sample(sample_args, [p, q]) adjective = (random.choice(['наибольший', 'самый большой']) + ' общий ' + random.choice(['знаменатель'])) if is_question: template = random.choice([ 'Расчитайте {adjective} {p} и {q}.', 'Чему равен {adjective} {p} и {q}?', ]) return example.Problem(question=example.question(context, template, adjective=adjective, p=p, q=q), answer=value) else: return composition.Entity( context=context, value=value, description='Пусть {self} - это {adjective} {p} и {q}.', adjective=adjective, p=p, q=q)
def simplify_power(value, sample_args, context=None): """E.g., "Simplify ((x**2)**3/x**4)**2/x**3.".""" del value # unused if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() variable = sympy.symbols(context.pop(), positive=True) unsimplified = polynomials.sample_messy_power(variable, entropy) answer = unsimplified.sympy() template = random.choice([ 'Упростите {unsimplified} при условии, что переменная {variable} положительна.', ]) return example.Problem( example.question(context, template, unsimplified=unsimplified, variable=variable), answer)
def _add_question_or_entity(context, p, q, is_question): """Generates entity or question for adding p + q.""" value = p.value + q.value if is_question: # template = random.choice([ # '{p} + {q}', # '{p}+{q}', # 'Work out {p} + {q}.', # 'Add {p} and {q}.', # 'Put together {p} and {q}.', # 'Sum {p} and {q}.', # 'Total of {p} and {q}.', # 'Add together {p} and {q}.', # 'What is {p} plus {q}?', # 'Calculate {p} + {q}.', # 'What is {p} + {q}?', # ]) template = random.choice([ '{p} + {q}', '{p}+{q}', 'Рассчитайте {p} + {q}.', 'Сложите {p} и {q}.', 'Прибавьте {p} к {q}.', 'Найдите сумму {p} и {q}.', 'Чему равна сумма {p} и {q}.', 'Сколько получится, если сложить {p} и {q}.', 'Сколько будет {p} плюс {q}?', 'Вычислите {p} + {q}.', 'Чему равно {p} + {q}?', ]) return example.Problem( question=example.question(context, template, p=p, q=q), answer=value) else: return composition.Entity( context=context, value=value, description='Пусть {self} = {p} + {q}.', p=p, q=q)
def _conversion_fraction(context, is_train): """E.g., "How many grams are in three quarters of a kg?".""" dimension = random.choice(DIMENSIONS) # Limit probability of giving zero answer. allow_zero = random.random() < 0.2 # Repeat until we find a pair with an integral answer. (Avoids ambiguity with # decimals.) while True: base_unit, target_unit = random.sample(list(dimension.keys()), 2) base_value = number.non_integer_rational(2, signed=False) if train_test_split.is_train(base_value) != is_train: continue answer = (base_value * sympy.Rational(dimension[base_unit]) / sympy.Rational(dimension[target_unit])) if (abs(answer) <= 100000 and sympy.denom(answer) == 1 and (allow_zero or answer != 0)): break template, case = random.choice([ ('Сколько {target_name_skolko} в {base_value} {base_name_fraction}?', 'v'), ('Переведите {base_value} {base_name_fraction} в {target_name}?', 'perevedi'), ]) if sympy.denom(base_value) > 20 or random.choice([False, True]): base_value_string = base_value # Will be represented as e.g., 2/3. else: base_value_string = display.StringNumber(base_value, case=case, gender='fem') # e.g., two thirds # тут всегда единственное у меры question = example.question( context, template, base_name=base_unit.name, base_name_fraction=base_unit.name_perevedi[1], base_value=base_value_string, target_name=target_unit.name, target_name_skolko=target_unit.name_skolko) return example.Problem(question=question, answer=answer)
def _sub_question_or_entity(context, p, q, is_question): """Generates entity or question for subtraction p - q.""" value = p.value - q.value if is_question: # templates = [ # '{p} - {q}', # 'Work out {p} - {q}.', # 'What is {p} minus {q}?', # 'What is {p} take away {q}?', # 'What is {q} less than {p}?', # 'Subtract {q} from {p}.', # 'Calculate {p} - {q}.', # 'What is {p} - {q}?', # ] templates = [ '{p} - {q}', 'Рассчитайте {p} - {q}.', 'Сколько будет {p} минус {q}?', 'Сколько будет {p} отнять {q}?', 'Какое число на {q} меньше {p}?', 'Отнимите {q} от {p}.', 'Вычислите {p} - {q}.', 'Чему равно {p} - {q}?', ] if sympy.Ge(p.value, q.value): # We calculate p - q, so the difference (|p - q|) is the correct answer. for adjective in ['разница']: for pair in ['{p} и {q}', '{q} и {p}']: templates.append('Чему равна {} {}?'.format(adjective, pair)) template = random.choice(templates) return example.Problem( question=example.question(context, template, p=p, q=q), answer=value) else: return composition.Entity( context=context, value=value, description='Пусть {self} = {p} - {q}.', p=p, q=q)
def div(value, sample_args, context=None): """Returns random question for dividing two numbers.""" del value # unused is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() entropy_1, entropy_q = _entropy_for_pair(entropy) q = number.integer(entropy_q, True, min_abs=1) if random.choice([False, True]): # Pick p/q with nice integer result. answer = number.integer(entropy_1, True) p = answer * q else: p = number.integer(entropy_1, True) answer = p / q p, q = context.sample(sample_args, [p, q]) if is_question: template = random.choice([ 'Разделите {p} на {q}.', 'Чему равно {p} разделить на {q}', 'Сколько получится, если {p} поделить на {q}?', 'Чему равен результат деления {p} на {q}.', ]) return example.Problem( question=example.question(context, template, p=p, q=q), answer=answer ) else: return composition.Entity( context=context, value=answer, description='Пусть {self} равно {p} разделить на {q}.', p=p, q=q)
def add_or_sub_in_base(sample_args): """Module for addition and subtraction in another base.""" context = composition.Context() entropy, sample_args = sample_args.peel() entropy_p, entropy_q = _entropy_for_pair(entropy) p = number.integer(entropy_p, signed=True) q = number.integer(entropy_q, signed=True) base = random.randint(2, 16) if random.choice([False, True]): answer = p + q template = 'По основанию {base}, чему равно {p} + {q}?' else: answer = p - q template = 'По основанию {base}, чему равно {p} - {q}?' return example.Problem( question=example.question( context, template, base=base, p=display.NumberInBase(p, base), q=display.NumberInBase(q, base)), answer=display.NumberInBase(answer, base))
def list_prime_factors(value, sample_args, context=None): """E.g., "What are the prime factors of 36?".""" del value # unused for now if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() entropy = max(1, entropy) integer = number.integer(entropy, signed=False, min_abs=2) (entity, ) = context.sample(sample_args, [integer]) prime_factors = sorted(sympy.factorint(integer).keys()) template = random.choice([ # 'What are the prime factors of {integer}?', # 'List the prime factors of {integer}.', 'Найдите простые делители числа {integer}?', 'Перечислите простые делители числа {integer}.', ]) return example.Problem(question=example.question( context, template, integer=entity.expression_else_handle), answer=display.NumberList(prime_factors))
def div_remainder(value, sample_args, context=None): """E.g., "What is the remainder when 27 is divided by 5?".""" is_question = context is None if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() if value is None: entropy_value = 1 + random.uniform(0, entropy / 3) entropy = max(0, entropy - entropy_value) value = number.integer(entropy_value, signed=False) entropy_a, entropy_q = entropy * np.random.dirichlet([1, 1]) a = number.integer(entropy_a, signed=False, min_abs=1) q = value + number.integer(entropy_q, signed=False, min_abs=1) p = a * q + value assert p % q == value p, q = context.sample(sample_args, [p, q]) if is_question: template = random.choice([ 'Расчитайте остаток от деления {p} на {q}.', 'Чему равен остаток деления {p} на {q}?', ]) return example.Problem(question=example.question( context, template, p=p.expression_else_handle, q=q.expression_else_handle), answer=value) else: return composition.Entity( context=context, value=value, description='Пусть {self} - остаток от деления {p} на {q}.', p=p, q=q)
def is_factor(value, sample_args, context=None): """E.g., "Is 5 a factor of 48?".""" del value # unused if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() entropy_factor = 1 + random.uniform(0, entropy / 3) entropy = max(0, entropy - entropy_factor) maybe_factor = number.integer(entropy_factor, False, min_abs=2) integer = maybe_factor * number.integer(entropy, False, min_abs=1) # Produce balanced classes. if random.choice([False, True]): # The following makes it not a factor. integer += random.randint(1, maybe_factor - 1) (entity, ) = context.sample(sample_args, [integer]) templates = [ # 'Is {maybe_factor} a factor of {value}?', # 'Is {value} a multiple of {maybe_factor}?', 'Является ли {maybe_factor} делителем {value}?', ] if maybe_factor == 2: templates += [ 'Является ли {value} четным?', ] template = random.choice(templates) answer = integer % maybe_factor == 0 return example.Problem(question=example.question( context, template, maybe_factor=maybe_factor, value=entity.expression_else_handle), answer=answer)