4

Is there a way, where I could automatically transform a string (using a command) like:

(1/SF) * (MDD\_a) * (1/LDD\_b) * (MBS\_b) * (1/SSA\_ab)

into a mathematical expression like:

$(\frac{1}{SF}) * (MDD\_a) * (\frac{1}{LDD\_b}) * (MBS\_b) * (\frac{1}{SSA\_ab})$

when then looks like:

enter image description here

I have several dynamic statements of the above form, which I would automatically transform to a mathematical expression.

Amanda
  • 387
  • no. as displayed math term i guess that you need to rewrite it into \[ \frac{1}{\mathrm{SF}}\mathrm{MDD}_a\frac{1}{\mathrm{LDD}_b}\mathrm{MBS}_b \frac{1}{\mathrm{SSA}_{ab}} = \frac{\mathrm{MDD}_a}{\mathrm{SF}}\frac{\mathrm{MBS}_b}{\mathrm{LDD}_b} \frac{1}{\mathrm{SSA}_{ab}} = ... \] – Zarko May 13 '19 at 08:06
  • @Zarko How could I write a command that transforms the text like (1/SF) * (MDD\_a) * (1/LDD\_b) * (MBS\_b) * (1/SSA\_ab) into a mathematical expression? – Amanda May 13 '19 at 08:15
  • presumably whatever is generating the original knows it is for tex since it is using \_ not _ in which case it would be much more reliable if it generated the fractions using \frac rather than an infix / – David Carlisle May 13 '19 at 08:44
  • as your image shows, do not use math italic for multiple letter identifiers like LDD you should use \mathrm as Zarko suggested. The math italic font uses wide spacing between the letters so they look like a product of variables not a single word. – David Carlisle May 13 '19 at 08:46
  • Which tex editor do you use? – Hafid Boukhoulda May 13 '19 at 10:00
  • @DavidCarlisle The program outputs a simple string without escaping any character (1/SF) * (MDD_a) * (1/LDD_b) * (MBS_b) * (1/SSA_ab), I was looking for a way, where I could transform this plain string into a mathematical expression. – Amanda May 13 '19 at 10:08
  • Which TeX engine do you use? pdf(La)TeX? Are you willing and able to switch to LuaLaTeX? And, should (say) MDD\_a really be rendered with an underscore, or would you rather get MDD_{a}, i.e., a as a subscript to the right of "MDD"? Please advise. – Mico May 13 '19 at 10:11
  • 1
    @Mico I am using LuaLatex – Amanda May 13 '19 at 10:12
  • Thanks. And, must you place parentheses around the terms, or could you let \frac{1}{SF} stand by itself? – Mico May 13 '19 at 10:15
  • Please see this answer, to see if it helps: https://tex.stackexchange.com/questions/332012/translate-in-line-equations-to-tex-code-any-package/332061#332061 – Steven B. Segletes May 13 '19 at 10:16
  • 1
    @Mico Can go without the parentheses. – Amanda May 13 '19 at 10:19

3 Answers3

3

Here's a LuaLaTeX-based solution, which makes use of Lua's powerful string.gsub and string.sub functions.

enter image description here

%%% Must be compiled under LuaLaTeX
\documentclass{article}
\usepackage{luacode} % for 'luacode' environment
\begin{luacode}
function nicemath ( s )
  s = s:gsub ( "%(([%w%_]+)/([%w%_]+)%)","\\frac{%1}{%2}" )
  s = s:gsub ( "(%a+)_(%a+)" , "%1_{%2}" )
  s = s:gsub ( "%u+" , "\\mathrm{%0}" )
  s = s:gsub ( "%*" , "\\cdot " )
  s = s:gsub ( "%b()", function ( x ) return x:sub ( 2 , -2 ) end ) -- optional
  tex.sprint ( s )
end
\end{luacode}
\newcommand\nicemath[1]{\directlua{nicemath(\luastringN{#1})}}

\begin{document}
\[
\nicemath{(1/SF) * (MDD_a) * (1/LDD_b) * (MBS_b) * (1/SSA_ab)}
\]
\end{document} 
Mico
  • 506,678
3

When you place the parentheses a little bit different, you can use ConTeXt's asciimath module.

\usemodule[asciimath]

\starttext

\startformula
    \asciimath{1/(SF) * MDD_a * 1/(LDD_b) * MBS_b * 1/(SSA_(ab))}
\stopformula

\stoptext

enter image description here

Henri Menke
  • 109,596
2

I start with using the exact and very unusual answer at Translate in-line equations to TeX code (Any Package?) (no changes) to interpret and translate the user's input.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{listofitems,ifthen}

\def\QS[#1]{%
  \if+\Qsep[#1]+\else%
  \if-\Qsep[#1]-\else%
  \if/\Qsep[#1]\over\else%
  \if=\Qsep[#1]=\else%
  \if^\Qsep[#1]^\else%
  \if(\Qsep[#1]\bgroup\left(\else%
  \if)\Qsep[#1]\right)\egroup\else%
  \if[\Qsep[#1]\bgroup\else%
  \if]\Qsep[#1]\egroup\else%
  \if*\Qsep[#1]\cdot\else%
  \if_\Qsep[#1]\expandafter\theund\else%
  \csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}%

\def\theund#1[#2]{_{\mathrm{#1[#2]}}}%

\setsepchar[@]{=@(||)||[||]@^@/||*@+||-@_@alpha||beta||pi||cos||sin||tan}

\makeatletter

\def\gQ[#1]{\edef\tmp{#1}\expandafter\g@addto@macro\expandafter\Z%
  \expandafter{\expandafter\Q\expandafter[\tmp]}}
\def\gQS[#1]{\edef\tmp{#1}\expandafter\g@addto@macro\expandafter\Z%
  \expandafter{\expandafter\QS\expandafter[\tmp]}}

\makeatother

\newcommand\interpreteq[1]{%
  \def\Z{}%
  \greadlist*\Q{#1}%
  \presentQ%
  \Z%
}

\newcounter{lindex}
\def\presentQ{% =
  \setcounter{lindex}{0}%
  \whiledo{\value{lindex}<\listlen\Q[]}{%
    \stepcounter{lindex}%
    \presentQA[\thelindex]%
    \ifnum\value{lindex}<\listlen\Q[]\relax%
      \gQS[\thelindex]%
    \fi%
  }%
}
\newcounter{lindexA}
\def\presentQA[#1]{% ()
  \setcounter{lindexA}{0}%
  \whiledo{\value{lindexA}<\listlen\Q[#1]}{%
    \stepcounter{lindexA}%
    \presentQB[#1,\thelindexA]%
    \ifnum\value{lindexA}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexA]%
    \fi%
  }
}
\newcounter{lindexB}
\def\presentQB[#1]{% ^
  \setcounter{lindexB}{0}%
  \whiledo{\value{lindexB}<\listlen\Q[#1]}{%
    \stepcounter{lindexB}%
    \presentQC[#1,\thelindexB]%
    \ifnum\value{lindexB}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexB]%
    \fi%
  }
}
\newcounter{lindexC}
\def\presentQC[#1]{% /*
  \setcounter{lindexC}{0}%
  \whiledo{\value{lindexC}<\listlen\Q[#1]}{%
    \stepcounter{lindexC}%
    \presentQD[#1,\thelindexC]%
    \ifnum\value{lindexC}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexC]%
    \fi%
  }
}
\newcounter{lindexD}
\def\presentQD[#1]{% +-
  \setcounter{lindexD}{0}%
  \whiledo{\value{lindexD}<\listlen\Q[#1]}{%
    \stepcounter{lindexD}%
    \presentQE[#1,\thelindexD]%
    \ifnum\value{lindexD}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexD]%
    \fi%
  }
}
\newcounter{lindexE}
\def\presentQE[#1]{% _
  \setcounter{lindexE}{0}%
  \whiledo{\value{lindexE}<\listlen\Q[#1]}{%
    \stepcounter{lindexE}%
    \presentQF[#1,\thelindexE]%
    \ifnum\value{lindexE}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexE]%
    \fi%
  }
}
\newcounter{lindexF}
\def\presentQF[#1]{% alpha beta pi cos sin tan
  \setcounter{lindexF}{0}%
  \whiledo{\value{lindexF}<\listlen\Q[#1]}{%
    \stepcounter{lindexF}%
    \gQ[#1,\thelindexF]%
    \ifnum\value{lindexF}<\listlen\Q[#1]\relax%
      \gQS[#1,\thelindexF]%
    \fi%
  }
}

% THESE ARE THE REDEFITIIONS FOR TRANSLATION
\usepackage{environ}

\def\QSALT[#1]{%
  \if+\Qsep[#1]+\else%
  \if-\Qsep[#1]-\else%
  \if/\Qsep[#1]\over\else%
  \if=\Qsep[#1]=\else%
  \if^\Qsep[#1]^\else%
  \if(\Qsep[#1]{\left(\else%
  \if)\Qsep[#1]\right)}\else%
  \if[\Qsep[#1]{\else%
  \if]\Qsep[#1]}\else%
  \if*\Qsep[#1]\cdot\else%
  \if_\Qsep[#1]\expandafter\theundALT\else%
  \expandafter\noexpand\csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}%

\def\theundALT#1[#2]{_{\noexpand\mathrm{#1[#2]}}}%

\makeatletter
\newcommand\translateeq[1]{%
  \bgroup%
  \let\QS\QSALT%
  \def\Z{}%
  \greadlist*\Q{#1}%
  \presentQ%
  \protected@edef\ZZ{\Z}
  \par\medskip\noindent%
  \parbox{\linewidth}{\detokenize\expandafter{\ZZ}}%
  \par\medskip%
  \egroup%
}
\makeatother

\NewEnviron{translateeqs}{\expandafter\nexteqn\BODY\par\relax}

\long\def\nexteqn#1\par#2\relax{%
  \translateeq{#1}\ifx\relax#2\else\nexteqn#2\relax\fi%
}
\begin{document}
\textbf{INTERPRETATING EQUATIONS}
\[
\interpreteq{(1/SF) * (MDD\_a) * (1/LDD\_b) * (MBS\_b) * (1/SSA\_ab)}
\]

\textbf{TRANSLATING EQUATIONS}

\translateeq{(1/SF) * (MDD\_a) * (1/LDD\_b) * (MBS\_b) * (1/SSA\_ab)}

\end{document}

enter image description here

Modifications can be made to reflect a different appearance.

For example, if \_ were, inside the definitions of \interpreteq and \translateeq, redefined as

\def\_{_}

and added to the parsing list via:

\setsepchar[@]{=@(||)||[||]@^@/||*@+||-@_||\_@alpha||beta||pi||cos||sin||tan}

then the result would look even better:

enter image description here

If the OP really wanted an asterisk rather than a \cdot in the output, then replacing \cdot with * in the definition of \QS and \QSALT would suffice, for example:

\def\QS[#1]{%
  \if+\Qsep[#1]+\else%
  \if-\Qsep[#1]-\else%
  \if/\Qsep[#1]\over\else%
  \if=\Qsep[#1]=\else%
  \if^\Qsep[#1]^\else%
  \if(\Qsep[#1]\bgroup\left(\else%
  \if)\Qsep[#1]\right)\egroup\else%
  \if[\Qsep[#1]\bgroup\else%
  \if]\Qsep[#1]\egroup\else%
  \if*\Qsep[#1]*\else%
  \if_\Qsep[#1]\expandafter\theund\else%
  \csname \Qsep[#1]\endcsname\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}%

enter image description here

  • I am using lualtex to render the document. As I do tex.print("$\string\\interpreteq{".. row_val .."}$"), I get an error saying https://ibb.co/yq1fQ5n – Amanda May 13 '19 at 10:51
  • @Amanda I am unable to access your error (site is blocked to me.). Plus, I don't speak lualatex, which may also be an impediment to my understanding your problem. – Steven B. Segletes May 13 '19 at 10:52
  • It says, Ambiguous; you need another { and }. \QS ... \if -\Qsep [#1] -\else \if /\Qsep [#1]\over .. – Amanda May 13 '19 at 11:12
  • 1
    @Amanda I have never seen such a warning and don't know how to interpret it in light of the listofitems package. It might have something to do with the way you structured your tex.print command, but I am not the one to help you in that regard. – Steven B. Segletes May 13 '19 at 11:16