1

Is it possible to write a regex which would take input like 'sqrt(2 * (2+2)) + sin(pi/6)' and transform it into '\sqrt{2 \cdot (2+2)} + \sin(\pi/6)'?

The problem is the 'sqrt' and parentheses in it. It is obvious I can't simply use something like this:

/sqrt\((.?)\)/ -> \\sqrt{$1}

because this code would create something like this '\sqrt{2 \cdot (2+2)) + \sin(\pi/6}'.

2
  • How many nested levels do you have? Are there expressions like sqrt(2 * (2+(4-2))) + sin(pi/6)? Commented Jul 26, 2015 at 12:41
  • I would like to have unlimited number of nested parentheses and functions could be nested too. But finally i found a solution which works! Commented Jul 26, 2015 at 22:54

3 Answers 3

1

My solution: it simply go throw the string converted to char array and tests if a current substring starts with $latex, if it does second for-cycle go from this point in different direction and by parentheses decides where the function starts and ends. (startsWith function)

Code:

public static function formatFunction($function, $latex, $input) {
    $input = preg_replace("/" . $function . "\(/", $latex . "{", $input);
    $arr = str_split($input);

    $inGap = false;
    $gap = 0;

    for ($i = count($arr) - 1; $i >= 0; $i--) {
        if (startsWith(substr($input, $i), $latex)) {
            for ($x = $i; $x < count($arr); $x++) {
                if ($arr[$x] == "(" || $arr[$x] == "{") { $gap++; $inGap = true; } 
                else if ($arr[$x] == ")" || $arr[$x] == "}") {  $gap--; }

                if ($inGap && $gap == 0) {
                    $arr[$x] = "}";
                    $inGap = false;
                    break;
                }
            }
        }
        $gap = 0;
    }

    return implode($arr);
}

Use:

self::formatFunction("sqrt", "\\sqrt", 
"sqrt(25 + sqrt(16 - sqrt(49)) + (7 + 1)) + sin(pi/2)");

Output:

\sqrt{25+\sqrt{16-\sqrt{49}}+(7+1)}+\sin (\pi/2)

Note: sin and pi aren't formated by this code, it's only str_replace function...

Sign up to request clarification or add additional context in comments.

Comments

0

In general, no regular expression can effectively handle nested parentheses. Sorry to be the bearer of bad news! The MathJAX parser library can interpret LaTeX equations and you could probably add a custom output routine to do what you want.

For TeX questions, you can also try http://tex.stackexchange.com .

1 Comment

Thanks, I use MathJax in my project, but I don't believe it could do this job (at least I can't imagine how), because it would have to somehow solve the problem i've ask about. Is there any other option how to do this in PHP?
0

Some time ago i soved a similar problem in such way. Maybe it will be helpful for you

$str = 'sqrt((2 * (2+2)) + sin(pi/(6+7)))';
$from = [];     // parentheses content
$to = [];       // patterns for replace #<number> 
$brackets = [['(', ')'], ['{', '}'], ['[', ']']]; // new parentheses for every level
$level = 0;
$count = 1;  // count or replace made
while($count) {
  $str = preg_replace_callback('(\(([^()]+)\))', 
           function ($m) use (&$to, &$from, $brackets, $level) {
             array_unshift($to, $brackets[$level][0] . $m[1] . $brackets[$level][1]);
             $i = '#' . (count($to)-1); // pattern for future replace. 
                                        // here it '#1', '#2'. 
                                        // Make it so they will be unique
             array_unshift($from, $i); 
             return $i; }, $str, -1, $count); 
  $level++;
  }

echo str_replace($from, $to, $str); // return content back
// sqrt[{2 * (2+2)} + sin{pi/(6+7)}]

I forgot all details, but it, seems, works

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.