電卓の入力を LaTeX に変換しようとしています。ユーザーがこれを入力した場合:
(3x^(x+(5/x)+(x/33))+y)/(32 + 5)
これを次のように変換する必要があります。
frac{3x^(x+frac{5}{x}+frac{x}{33})+y}{32 + 5x}
ただし、分子がいつ開始および終了するかを判断する際に問題があります。助言がありますか?
コンパイラを見てください
compiler.parse('(3*x**(x+(5/x)+(x/33))+y)/(32 + 5)')
戻り値
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))))))]))
これはより簡単に LaTeX コードに変換できます。各コード (Div、Add、Const、Name、Power など) とそのパラメーターを再帰的に処理し、適切な LateX コードを返すメソッドを作成する必要があります。
この種の変換用のパッケージは既に存在します: Py2Tex
このパッケージを再利用したい場合は、py2tex.Interpret
クラスを使用して再利用できます。
質問の正確な構文を使用したい場合は、電卓用のパーサーを作成できます。
#!/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))
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}}$
一般に、Python などの既存の言語の構文を使用する方が望ましい場合があります。