下記は数式をTeXのソースに変換するphpプログラムです。xmlで数式を受けて,xmlで変換後のソースを返すようになっています。複数の数式を変換するようになっています。
ソースをコピーして,張りつけたのですが,一部文字がおかしくなっているかも知れません。以前にバッククオートが変になっていたことがありました。
<?php
header(‘Access-Control-Allow-Origin:*’);
header(‘Access-Control-Allow-Headers:*’);
header(‘Access-Control-Allow-Methods:GET, POST, OPTIONS’);
header(‘Content-Type: text/plain’);
/*
* 試験的なプログラム。maximaの数式をtexにかえるもの。
* 式の頭から順に処理するタイプ。
* 複数の式を変換できるように変更した。式はxmlデータとしてもらう。
*/
# $sikiは以下で処理する、maximaの式
# $siki = “( 1 / 2 ) * x + m[x + 1] / y[2] + (x + 1) / (y – 3) + (x + 1) / y”;
# $siki = “((x + 1)) / (y – 3) + (x + 1) / y”;
# $siki = ” cos(x – 1) + log(y)”;
# $siki = “fun(x * y)”;
# $siki = “f[i + 1] / y^(x – 3)”;
# $siki = “bigsigma n + n^2 + cdot cdot cdot + n^k”;
# $siki = “v[0]^2 / g”;
# $siki = “x^2^z / 2”;
if ($HTTP_RAW_POST_DATA) {
parse_str($HTTP_RAW_POST_DATA);
} else {
$param1 = $_POST[“param1”];
}
//$logfile = fopen(“/var/www/html/temporary/log.txt”,”w”);
//fputs($logfile,$HTTP_RAW_POST_DATA);
//fclose($logfile);
/*
$param1 = ‘<?xml version=”1.0″ encoding=”utf-8″?><root><folder>tmp1310093593530405</folder><question><num>1</num><AnswerTest>Equal_Com_Ass</AnswerTest><SAns>3*x^2</SAns><Errors></Errors><RawMark>1</RawMark><FeedBack></FeedBack><AnswerNote></AnswerNote></question><question><num>2</num><AnswerTest>Equal_Com_Ass</AnswerTest><SAns>3*sqrt(2)</SAns><Errors></Errors><RawMark>0</RawMark><FeedBack></FeedBack><AnswerNote>[[ATEqual_com_ass: (not AlgEquiv)]]</AnswerNote></question></root>’;
*/
$xml = simplexml_load_string($param1);
foreach ($xml->question as $q) {
$num_ary[] = $q->num;
$AnswerTest_ary[] = $q->AnswerTest;
$siki_ary[] = $q->SAns;
}
//echo sizeof($siki_ary).”\n”;
$tmpxml = “”;
for ($i4q = 0; $i4q < sizeof($siki_ary); $i4q = $i4q + 1) {
$tmp = $siki_ary[$i4q];
//echo $tmp.”\n”;
if (($AnswerTest_ary[$i4q] == ‘Selection’) || ($AnswerTest_ary[$i4q] == ‘Glossary’)) {
$tex_ary[$i4q] = $tmp;
} else {
$tmp = trim($tmp);
if (preg_match(‘/[^A-Za-z0-9. ,^*\-\/+=<>()\[\]]/’,$tmp)) {
$tex_ary[$i4q] = ‘error(character)’;
} else {
$tmp4maxima=”display2d:false;load(\”mactex-utilities.lisp\”); tex(“.$tmp.”);”;
$meirei=escapeshellarg($tmp4maxima);
$awasete=”/usr/bin/maxima -q –batch-string=$meirei”;
$str = shell_exec($awasete);
if (strpos($str,’$$’)) {
// $str_ary = explode(‘$$’,$str);
// echo $str_ary[1].”\n”;
$tex_ary[$i4q] = changeToTex($tmp);
} else {
$tex_ary[$i4q] = ‘error(expression)’;
}
}
}
$tmpxml = $tmpxml.”<question>\n<num>$num_ary[$i4q]</num>\n”;
$tmpxml = $tmpxml.”<AnswerTest>$AnswerTest_ary[$i4q]</AnswerTest>\n”;
$tmpxml = $tmpxml.”<SAns>$siki_ary[$i4q]</SAns>\n”;
$tmpxml = $tmpxml.”<tex>$tex_ary[$i4q]</tex>\n</question>\n\n”;
}
$xml4return = <<< end_of_quote
<?xml version=”1.0″ encoding=”utf-8″?>
<root>
$tmpxml
</root>
end_of_quote;
echo ($xml4return.”\n”);
function changeToTex($siki) {
global $bf,$taihi,$pf,$power;
$siki = escapeshellarg($siki);
//echo “siki = |$siki| \n”;
$siki = trim($siki, “‘”);
//echo “trim ->|$siki| \n”;
$siki = ereg_replace(‘([\*/\+\-])’,’ \1 ‘,$siki); # * / + – の前後にスペースを入れる
//echo “add space */+- ->|$siki| \n”;
$siki = ereg_replace(‘ +’,’ ‘,$siki); # スペースは2個連続しない
//echo “cut double space ->|$siki| \n”;
$siki = $siki.” “; # 最後にスペースが必要なようだ
//echo “add space at end ->|$siki| \n”;
$nagasa = strlen($siki);
$arr = str_split($siki);
$arr[$nagasa] = ‘ ‘;
$arr[$nagasa + 1] = ‘ ‘;
# echo “長さは”.$nagasa.”\n”;
//echo “arr -> |”.implode(“|”,$arr).”|”.”\n”;
$i = 0;
$bf = 0; # 括弧の階層を示すフラッグ、括弧があるとフラッグが1変化する
$taihi = ”; # @以下の要素を一時的に格納する変数
$youso[0] = ”; # texの式のテンポラリーな入れ物
$pf = 0; # 階乗の指数部のフラッグ
$power[0] = -1; # 階乗のカッコがどの$bfで開始されたのかを記録する変数。
while ($nagasa – 1 >= $i) {
//echo ” \$i = $i , |$arr[$i]| \n”;
if ($arr[$i] == ‘(‘ || $arr[$i] == ‘)’ || $arr[$i] == ‘[‘ || $arr[$i] == ‘]’) {
kcount ($arr[$i],$arr[$i + 1],$arr[$i + 2],$youso);
}
if (ereg(‘[a-zA-Z0-9.]’, $arr[$i])) {
alpha ($arr[$i],$arr[$i + 1],$arr[$i + 2],$youso);
}
if ($arr[$i] == “+” || $arr[$i] == “-” || $arr[$i] == “=”) {
epm ($arr[$i],$youso);
}
if ($arr[$i] == ” “) {
space ($arr[$i],$arr[$i + 1],$youso);
}
if ($arr[$i] == “*”) {
kakeru ($arr[$i],$youso);
}
if ($arr[$i] == “^”) {
kaijyou ($arr[$i],$youso);
}
if ($arr[$i] == “/”) {
waru ($arr[$i],$youso);
}
$i = $i + 1;
}
# 最後の処理
//echo “last |$youso[0]| pf = $pf, power = $power[$pf], bf = $bf \n”;
power_blackt_close($youso[0]);
//echo “power_blackt_close |$youso[0]| \n”;
#preg_match(‘/cos\\\\left\(([^\\\\]*)\\\\right\)\^\{([^}]*)\}/’,$youso[0],$tmpary);
#echo “preg |$tmpary[0]| |$tmpary[1]| |$tmpary[2]| \n”;
$youso[0] = preg_replace(‘/(cos|cos |sin|sin |tan|tan )\\\\left\((.*?)\\\\right\)\^\{([^}]*)\}/’,’\1^{\3}\left(\2\right)’,$youso[0]);
//echo “etc cos, sin |$youso[0]| \n”;
makefrac($youso[0]);
//$youso[0] = ereg_replace(‘[\\]cdot’,’\,’,$youso[0]);
//echo ‘this$$’.$youso[0].’$$that’.”\n”;
//echo $youso[0].”\n”;
return $youso[0];
} //changeToTex
function kcount ($arr,$arr1,$arr2,&$y) {
# 括弧のカウント
global $bf,$taihi,$pf,$power;
//echo “kcount start bf = $bf, y = |$y[$bf]| taihi = |$taihi| arr = |$arr| \n”;
switch($arr) {
case ‘(‘:
$y[$bf] = $y[$bf].$taihi;
$taihi = ”;
$bf = $bf + 1;
//echo “bf change -> $bf \n”;
$y[$bf] = ”;
break;
case ‘)’:
$y[$bf] = $y[$bf].$taihi;
power_blackt_close($y[$bf]);
#echo “kcount no1 |$y[$bf]| \n”;
#$y[$bf] = ereg_replace(‘\@\^’,’^’,$y[$bf]);
#echo “kcount no2 |$y[$bf]| \n”;
makefrac($y[$bf]);
$y[$bf] = ‘\left(‘.$y[$bf].’\right)’;
$bf = $bf – 1;
//echo “bf change -> $bf \n”;
$y[$bf] = $y[$bf].$y[$bf + 1].’@’;
$y[$bf] = ereg_replace(‘(.*)[\^][\\]left[\(](.*)[\\]right[\)]’,’\1^{\2}’,$y[$bf]);
$y[$bf] = ereg_replace(‘[\\]sqrt *[\\]left[\(](.*)[\\]right[\)]’,’\sqrt{\1}’,$y[$bf]);
//echo “kcount no3 |$y[$bf]| \n”;
$taihi = ”;
break;
case ‘[‘:
$y[$bf] = $y[$bf].$taihi;
$taihi = ”;
$bf = $bf + 1;
//echo “bf change -> $bf \n”;
$y[$bf] = ”;
break;
case ‘]’:
$y[$bf] = $y[$bf].$taihi;
$taihi = ”;
makefrac($y[$bf]);
$y[$bf] = ‘_{‘.$y[$bf].’}’;
$bf = $bf – 1;
//echo “bf change -> $bf \n”;
$y[$bf] = $y[$bf].$y[$bf + 1].’@’;
break;
}
//echo “kcount end bf = $bf, y = |$y[$bf]| taihi = |$taihi| arr = |$arr| \n”;
}
function alpha ($arr,$arr1,$arr2,&$y) {
# アルファベットと数字の処理、とにかく前の要素に継ぎ足す
global $bf,$taihi,$pf,$power;
//echo “alpha start y = |$y[$bf]| taihi = |$taihi| arr = |$arr| \n”;
$taihi = $taihi.$arr;
# echo “alpha $taihi \n”;
# 次の文字、さらにその次の文字を調べて、応答を変える。
if ($arr1 == ‘ ‘) {
if ($arr2 == ‘(‘) {
fun ($taihi);
} else {
greek ($taihi);
$y[$bf] = $y[$bf].$taihi.’@’;
//echo “alpha no1 y = |$y[$bf]| \n”;
$taihi = ”;
}
}
if ($arr1 == ‘(‘) {
fun($taihi);
}
if ($arr1 == ‘)’ || $arr1 == ‘[‘ || $arr1 == ‘]’ || $arr1 == ‘^’ || $arr1 == ‘/’ || $arr1 == ‘+’ || $arr1 == ‘-‘ || $arr1 == ‘*’ || $arr1 == ‘=’ ) {
greek ($taihi);
}
//echo “alpha end y = |$y[$bf]| taihi = |$taihi| \n”;
}
function fun(&$taihi) {
# 関数を認識する所、新しい関数を加えるならこの直下 。関数と認識したら@を付けない
//echo “fun startt taihi = |$taihi| \n”;
switch($taihi) {
case ‘cos’:
$taihi = ‘\cos’ ;
break;
case ‘sin’:
$taihi = ‘\sin’ ;
break;
case ‘tan’:
$taihi = ‘\tan’ ;
break;
case ‘log’:
$taihi = ‘\log’ ;
break;
case ‘sqrt’:
$taihi = ‘\sqrt’ ;
break;
case ‘Delta’:
$taihi = ‘\Delta’ ;
break;
case ‘exp’:
$taihi = ‘e^’ ;
break;
case ‘alpha’:
$taihi = ‘\alpha’ ;
break;
case ‘beta’:
$taihi = ‘\beta’ ;
break;
case ‘gamma’:
$taihi = ‘\gamma’ ;
break;
case ‘delta’:
$taihi = ‘\delta’ ;
break;
case ‘epsilon’:
$taihi = ‘\epsilon’ ;
break;
case ‘varepsilon’:
$taihi = ‘\varepsilon’ ;
break;
case ‘eta’:
$taihi = ‘\eta’ ;
break;
case ‘theta’:
$taihi = ‘\theta’ ;
break;
case ‘lambda’:
$taihi = ‘\lambda’ ;
break;
case ‘mu’:
$taihi = ‘\mu’ ;
break;
case ‘nu’:
$taihi = ‘\nu’ ;
break;
case ‘pi’:
$taihi = ‘\pi’ ;
break;
case ‘rho’:
$taihi = ‘\rho’ ;
break;
case ‘sigma’:
$taihi = ‘\sigma’ ;
break;
case ‘tau’:
$taihi = ‘\tau’ ;
break;
case ‘phi’:
$taihi = ‘\phi’ ;
break;
case ‘varphi’:
$taihi = ‘\varphi’ ;
break;
case ‘chi’:
$taihi = ‘\chi’ ;
break;
case ‘psi’:
$taihi = ‘\psi’ ;
break;
case ‘omega’:
$taihi = ‘\omega’ ;
break;
case ‘times’:
$taihi = ‘\times @’ ;
break;
case ‘pm’:
$taihi = ‘\pm @’ ;
break;
case ‘mp’:
$taihi = ‘\mp @’ ;
break;
default:
# 今のところ何もしない
}
//echo “fun end taihi = |$taihi| \n”;
}
function greek (&$taihi) {
# ギリシャ文字などを認識する所
//echo “greek start taihi = |$taihi| \n”;
switch($taihi) {
case ‘alpha’:
$taihi = ‘\alpha’ ;
break;
case ‘beta’:
$taihi = ‘\beta’ ;
break;
case ‘gamma’:
$taihi = ‘\gamma’ ;
break;
case ‘delta’:
$taihi = ‘\delta’ ;
break;
case ‘epsilon’:
$taihi = ‘\epsilon’ ;
break;
case ‘varepsilon’:
$taihi = ‘\varepsilon’ ;
break;
case ‘eta’:
$taihi = ‘\eta’ ;
break;
case ‘theta’:
$taihi = ‘\theta’ ;
break;
case ‘lambda’:
$taihi = ‘\lambda’ ;
break;
case ‘mu’:
$taihi = ‘\mu’ ;
break;
case ‘nu’:
$taihi = ‘\nu’ ;
break;
case ‘pi’:
$taihi = ‘\pi’ ;
break;
case ‘rho’:
$taihi = ‘\rho’ ;
break;
case ‘sigma’:
$taihi = ‘\sigma’ ;
break;
case ‘tau’:
$taihi = ‘\tau’ ;
break;
case ‘phi’:
$taihi = ‘\phi’ ;
break;
case ‘varphi’:
$taihi = ‘\varphi’ ;
break;
case ‘chi’:
$taihi = ‘\chi’ ;
break;
case ‘psi’:
$taihi = ‘\psi’ ;
break;
case ‘omega’:
$taihi = ‘\omega’ ;
break;
case ‘Delta’:
$taihi = ‘\Delta’ ;
break;
case ‘hbar’:
$taihi = ‘\hbar’ ;
break;
case ‘times’:
$taihi = ‘\times’ ;
break;
case ‘pm’:
$taihi = ‘\pm’ ;
break;
case ‘mp’:
$taihi = ‘\mp’ ;
break;
case ‘cdot’:
$taihi = ‘\cdot’ ;
break;
case ‘sum’:
$taihi = ‘\sum’ ;
break;
default:
# 今のところ何もしない
}
//echo “greek end taihi = |$taihi| \n”;
}
function epm ($arr,&$y) {
# =と+と-の処理
global $bf,$taihi,$pf,$power;
# +-を加えて区切る
//echo “epm start y = |$y[$bf]| and taihi = |$taihi| arr = |$arr| \n”;
$y[$bf] = $y[$bf].$taihi.$arr.’@’;
$taihi = ”;
//echo “epm end y = |$y[$bf]| and taihi = |$taihi| arr = |$arr| \n”;
}
function space ($arr,$arr1,&$y) {
# スペースの処理
global $bf,$taihi,$pf,$power;
# スペースを加えて区切る、関数名と括弧の隙間なら区切らない。sin (x)など。
//echo “space no1 |$y[$bf]| and taihi = |$taihi| \n”;
$y[$bf] = $y[$bf].$taihi;
$taihi = “”;
if ($arr1 == ‘(‘) {
if (ereg(‘@$’,$y[$bf])) {
$y[$bf] = $y[$bf].$arr.’@’;
//echo “space no2 |$y[$bf]| \n”;
} else {
$y[$bf] = $y[$bf].$arr; //関数と判断して@をつけない
//echo “space no3 |$y[$bf]| \n”;
}
} else {
if ($pf > 0 and $power[$pf] == $bf) {
power_blackt_close($y[$bf]);
# 階乗のカッコが閉じたのでmakefracなども? … ここでは必要なかった。
# ereg(‘\{([^{]*)\}@$’,$y[$bf],$naka); //最小の長さの{…}を抜き出す
# echo “naka 1 = |$naka[1]| \n”;
# makefrac($naka[1]);
# $naka[1] = ‘{‘.$naka[1].’}@’;
# echo “naka 2 = |$naka[1]| \n”;
# $y[$bf] = ereg_replace(‘\{([^{]*)\}@$’,$naka[1],$y[$bf]);
$y[$bf] = $y[$bf].” @”;
} else {
$y[$bf] = $y[$bf].$arr.’@’;
}
//echo “space no4 |$y[$bf]| \n”;
}
//echo “space end |$y[$bf]| \n”;
}
function power_blackt_close (&$yy) {
# 階乗のカッコを閉じる
global $bf,$taihi,$pf,$power;
//echo “power blacket close start yy = |$yy| \n”;
# @を削って
if (ereg(‘@$’,$yy)) {
$yy = substr($yy, 0, strlen($yy) – 1);
//echo ” cut @ at the end yy = |$yy| \n”;
}
while ($power[$pf] >= $bf) {
$yy = $yy.’}’;
$power[$pf] = -1;
$pf = $pf – 1;
//echo ” power down pf = $pf \n”;
}
//echo “power blacket close end yy = |$yy| \n”;
}
function kakeru ($arr,&$y) {
# *の処理、とにかく区切る
global $bf,$taihi,$pf,$power;
//echo “kakeru start y = |$y[$bf]| and taihi = |$taihi| arr = |$arr| \n”;
$y[$bf] = $y[$bf].$taihi.’\cdot ‘.’@’;
$taihi = ”;
//echo “kakeru end y = |$y[$bf]| and taihi = |$taihi| arr = |$arr| \n”;
}
function kaijyou ($arr,&$y) {
# ^の処理
global $bf,$taihi,$pf,$power;
//echo “kaijyou start y = |$y[$bf]| and taihi = |$taihi| arr = |$arr| \n”;
$y[$bf] = $y[$bf].$taihi;
//echo ” y = |$y[$bf]| \n”;
# 後ろに付いている@とスペースを削って^を付け足す
while (ereg(‘@$’,$y[$bf]) || ereg(‘ $’,$y[$bf])) {
$y[$bf] = substr($y[$bf], 0, strlen($y[$bf]) – 1);
//echo ” y = |$y[$bf]| \n”;
}
$taihi = ”;
$y[$bf] = $y[$bf].’^{‘;
$pf = $pf + 1;
$power[$pf] = $bf;
//echo “kaijyou end y = |$y[$bf]| \n”;
//echo “Power up pf = $pf , bf = $bf \n”;
}
function waru ($arr,&$y) {
# /の処理
global $bf,$taihi,$pf,$power;
//echo “waru start y = |$y[$bf]| and taihi = |$taihi| arr = |$arr| \n”;
$y[$bf] = $y[$bf].$taihi.’/’.’@’;
$taihi = ”;
//echo “waru end y = |$y[$bf]| and taihi = |$taihi| arr = |$arr| \n”;
}
function makefrac (&$yy) {
# 分数をつくるところ。割る記号と割る記号の間に+ー*=があると別な分数とみなす。そうでなければ同じ分数として取り扱う。
//echo “start makefrac yy = |$yy| \n”;
$tmparr = split(‘@’,$yy);
$tmpnagasa = sizeof($tmparr);
$tmparr[$tmpnagasa] = ”;
$j = 1;
$aida = 1;
while ($j <= $tmpnagasa – 2) {
if ($tmparr[$j] == ‘=’ || $tmparr[$j] == ‘+’ || $tmparr[$j] == ‘-‘ ||$tmparr[$j] == ‘\cdot ‘) {
$aida = $aida + 1;
}
if ($tmparr[$j] == ‘/’) {
$tmparr[$j] = ”;
if ($aida >= 1) {
$k = $j – 1;
while ($tmparr[$k] == ” | $tmparr[$k] == ‘ ‘) {
$k = $k – 1;
}
//echo ” no1 |$tmparr[$k]| \n”;
$tmparr[$k] = ereg_replace(‘^[\\]left[\(](.*)[\\]right[\)]$’,’\1′,$tmparr[$k]);
# echo “no2 |$tmparr[$k]| \n”;
# $tmparr[$k] = ereg_replace(‘(.*)[\\]left[\(]([^+-]*)[\\]right[\)]$’,’\1 \2′,$tmparr[$k]);
//echo ” no3 |$tmparr[$k]| \n”;
$tmparr[$k] = ‘\frac{‘.$tmparr[$k].’}’;
//echo ” no4 |$tmparr[$k]| \n”;
$k = $j + 1;
while ($tmparr[$k] == ” | $tmparr[$k] == ‘ ‘) {
$k = $k + 1;
}
$tmparr[$k] = ereg_replace(‘^[\\]left[\(](.*)[\\]right[\)]$’,’\1′,$tmparr[$k]);
# $tmparr[$k] = ereg_replace(‘(.*)[\\]left[\(]([^+-]+)[\\]right[\)]$’,’\1 \2′,$tmparr[$k]);
$tmparr[$k] = ‘{‘.$tmparr[$k].’}’;
//echo ” no5 |$tmparr[$k]| \n”;
$aida = 0;
} else {
$k = $j – 1;
while ($tmparr[$k] == ” | $tmparr[$k] == ‘ ‘) {
$k = $k – 1;
}
if (ereg(‘[\+\-]’, $tmparr[$k])) {
$tmp = ereg_replace(‘{(.+)}’,’\left(\1\right)’,$tmparr[$k]);
} else {
$tmp = ereg_replace(‘{(.+)}’,’\1′,$tmparr[$k]);
}
$m = $j + 1;
while ($tmparr[$m] == ” | $tmparr[$m] == ‘ ‘) {
$m = $m + 1;
}
$tmparr[$k] = ‘{‘.$tmp.’ \cdot ‘.$tmparr[$m].’}’;
//echo ” no6 |$tmparr[$k]| \n”;
$tmparr[$m] = ”;
$aida = 0;
}
}
$j = $j + 1;
}
$yy = implode(“@”,$tmparr); #バグ取りのため、本当は@をはさむ必要はない。
//echo “end makefrac yy = |$yy| \n”;
$yy = ereg_replace(‘@’,”,$yy);
$yy = ereg_replace(‘ +’,’ ‘,$yy); # スペースは2個連続しない
$yy = trim($yy);
//echo “stop makefrac yy = |$yy| \n”;
}
?>