5
\$\begingroup\$

I am converting natural math expressions with fractions to Latex code.

What I have done seems to work on examples I've tested, but I'm not sure if the algorithm is safe. And maybe the string part could be improved.

Maybe a better approach could be replace the / from left to right, but how in my case target the next?

  • By a generic pattern that matches the 3 cases at once.
  • By selecting specific / and passing tests on it and remplacing it after.

I don't know how to make that.

Some examples

((a)/(b))/(c)   ->   \dfrac{\dfrac{a}{b}}{c}
(a)/((b)/(c))   ->   \dfrac{a}{\dfrac{b}{c}}
(a)/(b)/(c)/(d)    ->   \dfrac{\dfrac{\dfrac{a}{b}}{c}}{d}
((a)/(b))/((c)/(d)) ->    \dfrac{\dfrac{a}{b}}{\dfrac{c}{d}}

My try :

function ToFrac (s)
    while s:find ("/") ~= nil
    do

    -- Remplace : \dfrac{}{}/() -> \dfrac{\dfrac...}{}
    if ( s:find ( '\\dfrac%b{}%b{}/%b()' , j ) ~= nil )
    then
    x,y,num,den = s:find( '(\\dfrac%b{}%b{})/(%b())' )
    den = den:gsub( '.(.+).' , '%1' )
    s = s:gsub( '(\\dfrac%b{}%b{})/(%b())',
                            "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    -- Remplace : ()/\dfrac{}{} -> \dfrac{()}{\dfrac...}
    if ( s:find ( '(%b()/\\dfrac%b{}%b{}' ) ~= nil )
    then
    x,y,num,den = s:find( '((%b())/(\\dfrac%b{}%b{})' )
    num = num:gsub( '.(.+).' , '%1' )
    s = s:gsub( '((%b())/()\\dfrac%b{}%b{})',
                            "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    -- Remplace : ()/() -> \dfrac{}{}
    if ( s:find ( '%b()/%b()' , 1 ) ~= nil )
    then
        x,y,num,den = s:find( '(%b())/(%b())' )
        num = num:gsub( '.(.+).' , '%1' )
        den = den:gsub( '.(.+).' , '%1' )
        s = s:gsub( '(%b())/(%b())',
                        "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    end -- while

    return (s)

end

s = "((a)/(b))/(c)"
print (s, ToFrac(s))

s = "(a)/((b)/(c))"
print (s, ToFrac(s))

s = "(a)/(b)/(c)/(d)"
print (s, ToFrac(s))

s = "((a)/(b))/((c)/(d))"
print (s, ToFrac(s))
\$\endgroup\$
  • 2
    \$\begingroup\$ Can you explain a bit more exactly what your code is doing? Preferably with input/output examples? \$\endgroup\$ – Simon Forsberg Jul 20 '15 at 21:25
  • \$\begingroup\$ I put some examples. \$\endgroup\$ – Tarass Jul 21 '15 at 5:12
  • 2
    \$\begingroup\$ In your third example, the parentheses don't match. \$\endgroup\$ – 200_success Jul 21 '15 at 5:44
  • \$\begingroup\$ I made the correction. \$\endgroup\$ – Tarass Jul 21 '15 at 5:53
  • \$\begingroup\$ I can't do it now, but I think the right solution is to index each / as /i, then replace each /i one by one using the right pattern. \$\endgroup\$ – Tarass Jul 21 '15 at 5:56
3
\$\begingroup\$

You can use a recursive function with the pattern %b() as follows:

function ToFrac( sInput )
    local tStack = {}
    for sOperand in sInput:gmatch "%b()" do
        table.insert( tStack, sOperand:sub(2, -2) )
    end
    while true do
        if #tStack <= 1 then break end
        local sNumerator = table.remove( tStack, 1 )
        if sNumerator:find '/' then sNumerator = ToFrac( sNumerator ) end
        local sDenominator = table.remove( tStack, 1 )
        if sDenominator:find '/' then sDenominator = ToFrac( sDenominator ) end
        table.insert( tStack, 1, ([[\dfrac{%s}{%s}]]):format(sNumerator, sDenominator) )
    end
    return tStack[1]
end

Here, I'm storing the operands as nodes in a stack. I tested the above function for the inputs:

local s = {
    "((a)/(b))/(c)",
    "(a)/((b)/(c))",
    "(a)/((b)/(c))/(d)",
    "(a)/(b)/(c)/(d)",
    "((a)/(b))/((c)/(d))",
}

for k, v in pairs(s) do
    print( v, ToFrac(v) )
end

The final results were:

((a)/(b))/(c)   \dfrac{\dfrac{a}{b}}{c}
(a)/((b)/(c))   \dfrac{a}{\dfrac{b}{c}}
(a)/((b)/(c))/(d)   \dfrac{\dfrac{a}{\dfrac{b}{c}}}{d}
(a)/(b)/(c)/(d) \dfrac{\dfrac{\dfrac{a}{b}}{c}}{d}
((a)/(b))/((c)/(d)) \dfrac{\dfrac{a}{b}}{\dfrac{c}{d}}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.