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}.', ]) return example.Problem(question=example.question( context, template, integer=entity.expression_else_handle), answer=display.NumberList(prime_factors))
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([ 'Sederhanakan {unsimplified} dengan asumsi {variable} adalah positif.', ]) return example.Problem( example.question(context, template, unsimplified=unsimplified, variable=variable), answer)
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([ 'Expand {expression}.' ]) return example.Problem( question=example.question(context, template, expression=expression_), answer=expanded)
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([ 'Express {expression} as {canonical} and give {target}.', 'Rearrange {expression} to {canonical} and give {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 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([ 'Divide {p} by {q}.', '{p} divided by {q}', 'What is {p} divided by {q}?', 'Calculate {p} divided by {q}.', ]) return example.Problem( question=example.question(context, template, p=p, q=q), answer=answer ) else: return composition.Entity( context=context, value=answer, description='Let {self} be {p} divided by {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 = 'In base {base}, what is {p} + {q}?' else: answer = p - q template = 'In base {base}, what is {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 simplify_surd(value, sample_args, context=None): """E.g., "Simplify (2 + 5*sqrt(3))**2.".""" del value # unused if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() while True: base = random.randint(2, 20) if sympy.Integer(base).is_prime: break num_primes_less_than_20 = 8 entropy -= math.log10(num_primes_less_than_20) exp = _sample_surd(base, entropy, max_power=2, multiples_only=False) simplified = sympy.expand(sympy.simplify(exp)) template = random.choice([ 'Simplify {exp}.', ]) return example.Problem( question=example.question(context, template, exp=exp), answer=simplified)
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}?', ]) return example.Problem( question=example.question(context, template, op=op), answer=value) else: return composition.Entity( context=context, value=value, expression=op, description='Let {self} be {op}.', op=op)
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}?', ] 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='Let {self} = {p} * {q}.', p=p, q=q)
def _make_comparison_question(context, left, right): """Makes a question for comparing two values.""" if random.choice([False, True]) and sympy.Ne(left.value, right.value): # Do question of form: "Which is bigger: a or b?". if random.choice([False, True]): answer = (left.handle if sympy.Gt(left.value, right.value) else right.handle) template = random.choice([ 'Which is bigger: {left} or {right}?', 'Which is greater: {left} or {right}?', ]) else: answer = (left.handle if sympy.Lt(left.value, right.value) else right.handle) template = random.choice([ 'Which is smaller: {left} or {right}?', ]) return example.Problem(question=example.question(context, template, left=left, right=right), answer=answer) comparisons = { '<': sympy.Lt, '<=': sympy.Le, '>': sympy.Gt, '>=': sympy.Ge, '=': sympy.Eq, '!=': sympy.Ne, } templates = { '<': [ 'Is {left} ' + ops.LT_SYMBOL + ' {right}?', 'Is {left} less than {right}?', 'Is {left} smaller than {right}?', ], '<=': [ 'Is {left} ' + ops.LE_SYMBOL + ' {right}?', 'Is {left} less than or equal to {right}?', 'Is {left} at most {right}?', 'Is {left} at most as big as {right}?', ], '>': [ 'Is {left} ' + ops.GT_SYMBOL + ' {right}?', 'Is {left} greater than {right}?', 'Is {left} bigger than {right}?', ], '>=': [ 'Is {left} ' + ops.GE_SYMBOL + ' {right}?', 'Is {left} greater than or equal to {right}?', 'Is {left} at least {right}?', 'Is {left} at least as big as {right}?', ], '=': [ 'Does {left} ' + ops.EQ_SYMBOL + ' {right}?', 'Are {left} and {right} equal?', 'Is {left} equal to {right}?', 'Do {left} and {right} have the same value?', ], '!=': [ 'Is {left} ' + ops.NE_SYMBOL + ' {right}?', 'Is {left} not equal to {right}?', 'Are {left} and {right} unequal?', 'Are {left} and {right} nonequal?', 'Are {left} and {right} non-equal?', 'Do {left} and {right} have different values?', ], } comparison = random.choice(list(comparisons.keys())) template = random.choice(templates[comparison]) question = example.question(context, template, left=left, right=right) answer = comparisons[comparison](left.value, right.value) return example.Problem(question=question, answer=answer)