Data Structure for Math formulae

65 Views Asked by At

I am working on a python script that generates pdfs for math-tests via pylatex. So far I am using

str(random.randint(8,32)) +' + ' + str(random.randint(8,121))

and similar for generating randomized assignments.

I don't want to hard-code everything like above but I want to use a database approach to store possible assignments. My idea in this direction is a relational database

(student) --n (assignment_type)

where the students each get personilized assignments, for instance Peter will get assigments of the type

( (random sign) (random number 2-8) x (+ or -) (random sign) (random number))    (*)

and

( (random number 2323-9999):11)

I am unsure on how to save this datastructure in a database and how to translate it into python code. My idea here is for the database table 'assignment_type':

INT number of randomized vars
INT number of signs
ARRAY List of signs
ARRAY (lower und upper bound for each random number)
STRING '(s1r1s2r1)'

Where '(s1r1s2(s3r1))' would be translated in python to the above problem (*) ("( sign1 random1 sign2 (sign3)random2)") I am very unsure if this way of handling the problem is a stupid idea. I ask you hereby to review my approach and if possible point me in a better direction of handling this kind of data-structure.

1

There are 1 best solutions below

1
On

A quick idea:

First, define a few random functions for later use.

import random

def sign_num(a, b):
  n = random.randint(a, b)
  if random.random() < 0.5:
    return '(-{})'.format(n)
  else:
    return str(n)

def num(a, b):
  return str(random.randint(a,b))

def add(a, b, parens=False):
  n1 = num(a, b)
  n2 = num(a, b)
  if parens:
    return '({} + {})'.format(n1, n2)
  else:
    return '{} + {}'.format(n1, n2)

def sign_add(a, b, parens=False):
  n1 = sign_num(a, b)
  n2 = sign_num(a, b)
  if parens:
    return '({} + {})'.format(n1, n2)
  else:
    return '{} + {}'.format(n1, n2)

Then, make a dict with reference to all these functions:

dico = {'NUM': num, 'SIGNNUM': sign_num, 'ADD': add, 'SIGN_ADD': sign_add}

Then, write your parsing functions:

def fill_in(txt):
  argv = txt.strip().split()
  return dico[argv[0]](int(argv[1]), int(argv[2]))

def parse(txt):
  if '[' not in txt:
    return txt
  else:
    i = txt.index('[')
    j = txt.index(']')
    return txt[:i] + fill_in(txt[i+1:j])  + parse(txt[j+1:])

Now you can call them on template strings:

parse('[NUM 3 9] x ([ADD 2 9])')
# '8 x (8 + 7)'

There is a ton of room for improvement. In particular, the function fill_in should be written in a way that handles variable number of arguments.