6

I'm trying to convert calculator input to LaTeX. if a user inputs this:

(3x^(x+(5/x)+(x/33))+y)/(32 + 5)

I have to convert it to this:

frac{3x^(x+frac{5}{x}+frac{x}{33})+y}{32 + 5x}

however I am having issues with determining when a numerator begins and ends. Any suggestions?

Jonathon Faust
  • 12,396
  • 4
  • 50
  • 63
tipu
  • 9,464
  • 15
  • 65
  • 98

3 Answers3

5

Have a look at compiler

compiler.parse('(3*x**(x+(5/x)+(x/33))+y)/(32 + 5)')

returns

Module(None, Stmt([Discard(Div((Add((Mul((Const(3), Power((Name('x'), Add((Add((Name('x'), Div((Const(5), Name('x'))))), Div((Name('x'), Const(33))))))))), Name('y'))), Add((Const(32), Const(5))))))]))

which could be more easily converted to LaTeX code. You will have to write methods, that handle each code (Div, Add, Const, Name, Power,...) and its parameters recursively and return appropriate LateX code.

eumiro
  • 207,213
  • 34
  • 299
  • 261
  • 1
    The `^` needs to be replaced with `**` otherwise Python will treat it as the `Bitwise-XOR` operator. – user225312 Feb 09 '11 at 09:44
  • i am testing that out, though i do not understand the return value at the moment, thanks. – tipu Feb 09 '11 at 09:46
  • @sukhbir - I have already replaced `3x` with `3*x`, and now edited your remark, thank you. – eumiro Feb 09 '11 at 09:50
  • @eumiro: :-) This seems like a nice solution, though I will wait for the OP to confirm whether this works (I am thinking how will this be converted to LaTex) before giving you an upvote! – user225312 Feb 09 '11 at 09:53
  • @sukhbir: this could very well work, but i am unsure with what to do with the return value. i'm playing with that at the moment. – tipu Feb 09 '11 at 09:57
  • @tipu - see the given link for compiler - it has a list of all types of objects and their respective parameters. – eumiro Feb 09 '11 at 10:20
  • this is pretty much the answer that will gets me closer to my goal. next problem is figuring out the nodes and their children =) – tipu Feb 09 '11 at 10:21
  • 1
    Do not use the 'compiler' module, it is deprecated since 2.6. See http://stackoverflow.com/questions/909092/why-is-the-compiler-package-discontinued-in-python-3 – Jérôme Radix Feb 09 '11 at 10:25
  • It's impossible to preserve brackets and ordering with this method, otherwise a pretty good idea. – shang Feb 09 '11 at 10:58
4

A package already exists for this kind of transformation : Py2Tex

If you want to reuse this package, you can use the py2tex.Interpret class to do so.

Jérôme Radix
  • 10,285
  • 4
  • 34
  • 40
2

If you'd like to use the exact syntax from your question then you could write a parser for the calculator:

#!/usr/bin/env python
from operator import add, div, mul, sub

from lepl  import Any, Delayed, Digit, Drop, DroppedSpace, Eos
from sympy import Symbol, latex, pprint

def Power(tokens):
    """x**(y**z)"""
    return reduce(lambda p, b: pow(b, p), reversed(tokens))

def Arithm(tokens):
    """(x op1 y) op2 z ..."""
    OP = { '*': mul, '/': div, '+': add, '-': sub, }
    tokens = iter(tokens)
    a = next(tokens)
    for op, b in zip(tokens, tokens):
        a = OP[op](a, b)
    return a

def makeparser():
    expr = Delayed()
    number = Digit()[1:,...] >> int # \d+
    symbol = Any('xyz') >> (lambda x: Symbol(bytes(x))) # unicode -> str
    muldiv_op = Any('*/')[:1] > (lambda x: x[0] if x else '*') # xy -> x*y
    power_op = Drop('^') | Drop('**') # both stand for pow(x, y)

    with DroppedSpace(): # ignore spaces
        term = number | symbol | Drop('(') & expr & Drop(')')
        power   = term & (power_op  & term)[:] > Power
        factor = power & (muldiv_op & power)[:] > Arithm
        expr += factor & (Any('-+') & factor)[:] > Arithm
        line = expr & Eos()
    return line.get_parse()

parse = makeparser()
[expr] = parse('(3x^(x+(5/x)+(x/33))+y)/(32 + 5)')
pprint(expr)
print(latex(expr))

Output

        34⋅x   5
        ──── + ─
         33    x
y    3⋅x        
── + ───────────
37        37    
$\frac{1}{37} y + \frac{3}{37} x^{\frac{34}{33} x + \frac{5}{x}}$

In general it might be preferable to use syntax for an existing language such as Python.

jfs
  • 399,953
  • 195
  • 994
  • 1,670