Work is the refuge of people who have nothing better to do. : Oscar Wilde

Friday, December 7, 2007

Limitless Supplies of Algebra Exercises

Some students learning to simplify algebraic expressions dependably may benefit from drills. Generating drill examples, and simplifying them, is a tedious business that can be done readily using open source software. Here I use the Python language with the sympy module.

I am using a slight variation on Jerith's "CF grammar name generator" code to define and exercise a grammar for the expressions. Then I use sympy to simplify them. (Because I want to avoid any need to go beyond a context-free grammar I replace the token 'x' with any of a number of 'variable names' after generating the expressions. Because sympy requires an explicit multiplication symbol, '*', I include provision for this in the grammar and then arrange to remove it after expression generation and simplification. I would arrange to generate HTML as output from this code except for the fact that the result seems to confuse Blogger.)

My thanks are due to Ondrej Certik and Alan Bromborsky on the sympy mailing list for help with means for inputting expressions to sympy.

import random
from re import compile
import sys
from sympy import *
import webbrowser

reNonTerminal = compile ( r"<(\w+)>" )

def nameGen ( nameGrammar ) :
nameStr = random . choice ( nameGrammar [ "expr" ] )
matchNonTerminal = reNonTerminal . search ( nameStr )
while matchNonTerminal :
subStr = random . choice ( nameGrammar [ matchNonTerminal . group ( 1 ) ] )
nameStr = reNonTerminal . sub ( subStr, nameStr, 1 )
matchNonTerminal = reNonTerminal . search ( nameStr )
return nameStr

exprGrammar = {
"expr" : [ " " ],
"term" : [ " *( *x )", " *( *x )", ],
"sign" : [ "+", "-", ],
"signSuppressingPlus" : [ '', '-', ],
"digit" : [ str ( digit ) for digit in range ( 10 ) + range ( 1, 10 ) + range ( 1, 10 ) ],
}

variables = [ 'a', 'b', 'c', 'd', 'f', 'g', 'h', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ]
x = Symbol ( 'x' )

for exprNumber in range ( 10 ) :
expr = nameGen ( exprGrammar )
variable = random . choice ( variables )
print expr . replace ( '*', '' ) . replace ( 'x', variable ),
print ' [%s]' % str ( sympify ( expr ) ) . replace ( '*', '' ) . replace ( 'x', variable ) . replace ( '(', '' ) . replace ( ')', '' )