let trieMap0 = {" And ":"&"," and ":"&"," AND ":"&"," Or ":"|"," or ":"|"," OR ":"|"," In ":"∈"," in ":"∈"," IN ":"∈"," Not In ":"∉"," not in ":"∉"," NOT IN ":"∉"," Mod ":"\\mod"," mod ":"\\mod"," MOD ":"\\mod"," % ":"\\mod"," Perm ":"\\perm"," perm ":"\\perm"," PERM ":"\\perm"," Comb ":"\\comb"," comb ":"\\comb"," COMB ":"\\comb"," choose ":"\\comb"," CHOOSE ":"\\comb"," Choose ":"\\comb","! ":"!_"};
let trieMap1 = {"Math.sin(":"sin(","math.sin(":"sin(","MATH.SIN(":"sin(","Math.Sin(":"sin(","Math.cos(":"cos(","math.cos(":"cos(","MATH.COS(":"cos(","Math.Cos(":"cos(","Math.tan(":"tan(","math.tan(":"tan(","MATH.TAN(":"tan(","Math.Tan(":"tan(","Math.sec(":"sec(","math.sec(":"sec(","MATH.SEC(":"sec(","Math.Sec(":"sec(","Math.csc(":"csc(","math.csc(":"csc(","MATH.CSC(":"csc(","Math.Csc(":"csc(","Math.cot(":"cot(","math.cot(":"cot(","MATH.COT(":"cot(","Math.Cot(":"cot(","Math.sinh(":"sinh(","math.sinh(":"sinh(","MATH.SINH(":"sinh(","Math.Sinh(":"sinh(","Math.cosh(":"cosh(","math.cosh(":"cosh(","MATH.COSH(":"cosh(","Math.Cosh(":"cosh(","Math.tanh(":"tanh(","math.tanh(":"tanh(","MATH.TANH(":"tanh(","Math.Tanh(":"tanh(","Math.asin(":"arcsin(","math.asin(":"arcsin(","MATH.ASIN(":"arcsin(","Math.Asin(":"arcsin(","Math.acos(":"arccos(","math.acos(":"arccos(","MATH.ACOS(":"arccos(","Math.Acos(":"arccos(","Math.atan(":"arctan(","math.atan(":"arctan(","MATH.ATAN(":"arctan(","Math.Atan(":"arctan(","Math.asinh(":"arcsinh(","math.asinh(":"arcsinh(","MATH.ASINH(":"arcsinh(","Math.Asinh(":"arcsinh(","Math.acosh(":"arccosh(","math.acosh(":"arccosh(","MATH.ACOSH(":"arccosh(","Math.Acosh(":"arccosh(","Math.atanh(":"arctanh(","math.atanh(":"arctanh(","MATH.ATANH(":"arctanh(","Math.Atanh(":"arctanh(","Math.log2(":"log_{2}(","math.log2(":"log_{2}(","MATH.LOG2(":"log_{2}(","Math.Log2(":"log_{2}(","Math.log10(":"log_{10}(","math.log10(":"log_{10}(","MATH.LOG10(":"log_{10}(","Math.Log10(":"log_{10}(","Math.fabs(":"abs(","math.fabs(":"abs(","MATH.FABS(":"abs(","Math.Fabs(":"abs(","Math.gcd(":"gcd(","math.gcd(":"gcd(","MATH.GCD(":"gcd(","Math.Gcd(":"gcd(","Math.comb(":"comb(","math.comb(":"comb(","MATH.COMB(":"comb(","Math.Comb(":"comb(","Math.perm(":"perm(","math.perm(":"perm(","MATH.PERM(":"perm(","Math.Perm(":"perm(","Math.fmod(":"mod(","math.fmod(":"mod(","MATH.FMOD(":"mod(","Math.Fmod(":"mod(","Math.exp(":"e^(","math.exp(":"e^(","MATH.EXP(":"e^(","Math.Exp(":"e^(","Math.pow(":"pow(","math.pow(":"pow(","MATH.POW(":"pow(","Math.Pow(":"pow(","**":"^","Math.floor(":"floor(","math.floor(":"floor(","MATH.FLOOR(":"floor(","Math.Floor(":"floor(","Math.ceil(":"ceil(","math.ceil(":"ceil(","MATH.CEIL(":"ceil(","Math.Ceil(":"ceil(","Math.round(":"round(","math.round(":"round(","MATH.ROUND(":"round(","Math.Round(":"round(","Math.max(":"max(","math.max(":"max(","MATH.MAX(":"max(","Math.Max(":"max(","Math.min(":"min(","math.min(":"min(","MATH.MIN(":"min(","Math.Min(":"min(","Math.pi":"π","math.pi":"π","MATH.PI":"π","Math.Pi":"π","Math.PI":"π","math.Pi":"π","Math.e":"e","math.e":"e","MATH.E":"e","Math.E":"e","math.E":"e","Math.sqrt2":"sqrt(2)","math.sqrt2":"sqrt(2)","MATH.SQRT2":"sqrt(2)","Math.Sqrt2":"sqrt(2)","Math.sqrt(":"sqrt(","math.sqrt(":"sqrt(","MATH.SQRT(":"sqrt(","Math.Sqrt(":"sqrt(","Math.sqrt1_2":"sqrt(1/2)","math.sqrt1_2":"sqrt(1/2)","MATH.SQRT1_2":"sqrt(1/2)","Math.Sqrt1_2":"sqrt(1/2)","Math.log2e":"log_{2}(e)","math.log2e":"log_{2}(e)","MATH.LOG2E":"log_{2}(e)","Math.Log2E":"log_{2}(e)","Math.log10e":"log_{10}(e)","math.log10e":"log_{10}(e)","MATH.LOG10E":"log_{10}(e)","Math.Log10E":"log_{10}(e)","Math.ln2":"log_{e}(2)","math.ln2":"log_{e}(2)","MATH.LN2":"log_{e}(2)","Math.Ln2":"log_{e}(2)","Math.ln10":"log_{e}(10)","math.ln10":"log_{e}(10)","MATH.LN10":"log_{e}(10)","Math.Ln10":"log_{e}(10)","Math.tau":"τ","math.tau":"τ","MATH.TAU":"τ","Math.Tau":"τ","infinity":"∞","INFINITY":"∞","Infinity":"∞","\\infty":"∞","\\INFTY":"∞","\\Infty":"∞","\\cdot":"*","\\CDOT":"*","\\Cdot":"*","\\times":"*","\\TIMES":"*","\\Times":"*","\\max":"max","\\MAX":"max","\\Max":"max","\\min":"min","\\MIN":"min","\\Min":"min","product(":"prod(","PRODUCT(":"prod(","Product(":"prod(","log[":"log_[","LOG[":"log_[","Log[":"log_[","\\log_":"\\log_","\\LOG_":"\\log_","\\Log_":"\\log_","\\log":"\\log_{e}","\\LOG":"\\log_{e}","\\Log":"\\log_{e}","\\ln":"\\log_{e}","\\LN":"\\log_{e}","\\Ln":"\\log_{e}","log(":"log_{e}(","LOG(":"log_{e}(","Log(":"log_{e}(","ln(":"log_{e}(","LN(":"log_{e}(","Ln(":"log_{e}(","log2(":"log_{2}(","LOG2(":"log_{2}(","Log2(":"log_{2}(","log3(":"log_{3}(","LOG3(":"log_{3}(","Log3(":"log_{3}(","log4(":"log_{4}(","LOG4(":"log_{4}(","Log4(":"log_{4}(","log5(":"log_{5}(","LOG5(":"log_{5}(","Log5(":"log_{5}(","log6(":"log_{6}(","LOG6(":"log_{6}(","Log6(":"log_{6}(","log7(":"log_{7}(","LOG7(":"log_{7}(","Log7(":"log_{7}(","log8(":"log_{8}(","LOG8(":"log_{8}(","Log8(":"log_{8}(","log9(":"log_{9}(","LOG9(":"log_{9}(","Log9(":"log_{9}(","log10(":"log_{10}(","LOG10(":"log_{10}(","Log10(":"log_{10}(","log_10":"log_{10}","LOG_10":"log_{10}","Log_10":"log_{10}","\\log\\log":"\\loglog","\\LOG\\LOG":"\\loglog","\\Log\\Log":"\\loglog","\\log\\log\\log":"\\logloglog","\\LOG\\LOG\\LOG":"\\logloglog","\\Log\\Log\\Log":"\\logloglog","loglog(":"loglog(","LOGLOG(":"loglog(","Loglog(":"loglog(","\\exp":"e^","\\EXP":"e^","\\Exp":"e^","exp(":"e^(","EXP(":"e^(","Exp(":"e^(","\\div":"/","\\DIV":"/","\\Div":"/","\\in":"∈","\\IN":"∈","\\In":"∈","\\not\\in":"∉","\\NOT\\IN":"∉","\\Not\\In":"∉","\\notin":"∉","\\NOTIN":"∉","\\Notin":"∉","\\pmod":"%","\\PMOD":"%","\\Pmod":"%","\\mod":"%","\\MOD":"%","\\Mod":"%","\\pm":"±","\\PM":"±","\\Pm":"±","\\plusmn":"±","\\PLUSMN":"±","\\Plusmn":"±","\\neq":"≠","\\NEQ":"≠","\\Neq":"≠","!==":"≠","!=":"≠","\\gt":">","\\GT":">","\\Gt":">","\\lt":"<","\\LT":"<","\\Lt":"<","\\ge":"≥","\\GE":"≥","\\Ge":"≥","\\geq":"≥","\\GEQ":"≥","\\Geq":"≥",">=":"≥","\\le":"≤","\\LE":"≤","\\Le":"≤","\\leq":"≤","\\LEQ":"≤","\\Leq":"≤","<=":"≤","\\lparen":"(","\\LPAREN":"(","\\Lparen":"(","\\rparen":")","\\RPAREN":")","\\Rparen":")","\\left(":"(","\\LEFT(":"(","\\Left(":"(","\\right)":")","\\RIGHT)":")","\\Right)":")","\\lfloor":"⌊","\\LFLOOR":"⌊","\\Lfloor":"⌊","\\rfloor":"⌋","\\RFLOOR":"⌋","\\Rfloor":"⌋","\\lceil":"⌈","\\LCEIL":"⌈","\\Lceil":"⌈","\\rceil":"⌉","\\RCEIL":"⌉","\\Rceil":"⌉","ceiling(":"ceil(","CEILING(":"ceil(","Ceiling(":"ceil(","\\Pi":"Π","\\Alpha":"Α","\\Beta":"Β","\\Gamma":"Γ","\\Delta":"Δ","\\Epsilon":"Ε","\\Zeta":"Ζ","\\Eta":"Η","\\Theta":"Θ","\\Iota":"Ι","\\Kappa":"Κ","\\Lambda":"Λ","\\Mu":"Μ","\\Nu":"Ν","\\Xi":"Ξ","\\Omicron":"Ο","\\Rho":"Ρ","\\Sigma":"Σ","\\Tau":"Τ","\\Upsilon":"Υ","\\Phi":"Φ","\\Chi":"Χ","\\Psi":"Ψ","\\Omega":"Ω","\\pi":"π","\\alpha":"α","\\beta":"β","\\gamma":"γ","\\delta":"δ","\\epsilon":"ε","\\zeta":"ζ","\\eta":"η","\\theta":"θ","\\iota":"ι","\\kappa":"κ","\\lambda":"λ","\\mu":"μ","\\nu":"ν","\\xi":"ξ","\\omicron":"ο","\\rho":"ρ","\\sigma":"σ","\\tau":"τ","\\upsilon":"υ","\\phi":"φ","\\chi":"χ","\\psi":"ψ","\\omega":"ω"};
let root0 = newNode();
// Construct trie
for (var i in trieMap0){
trieInsert(i,root0);
}
let root1 = newNode();
// Construct trie
for (var i in trieMap1){
trieInsert(i,root1);
}
function newNode() {
var obj = {};
obj.isEnd = false;
obj.children = {};
return obj;
}
//Adds a key to the Trie
function trieInsert(key, pCrawl) {
let len = key.length;
var index;
for (var level = 0; level < len; level++) {
index = key[level];
if (pCrawl.children[index] == null) {
pCrawl.children[index] = newNode();
}
pCrawl = pCrawl.children[index];
}
pCrawl.isEnd = true;
}
// Returns true if key presents in trie, else false
function trieSearch(key, pCrawl) {
let len = key.length;
if (len == 0) { return; }
var index;
var longestMatch = -1;
for (var level = 0; level < len; level++) {
index = key[level];
if (pCrawl.children[index] == null) {
if (longestMatch >= 0) {
return [longestMatch + 1, key.substring(0, longestMatch + 1)];
}
else {
return false;
}
}
pCrawl = pCrawl.children[index];
if (pCrawl.isEnd) {
longestMatch = level;
}
}
if (longestMatch >= 0) {
return [longestMatch + 1, key.substring(0, longestMatch + 1)];
}
else {
return false;
}
}
function trieReplace0(input) {
var len = input.length;
for (var i = 0; i < input.length; i++) {
var ts = trieSearch(input.substring(i), root0);
if (ts) {
let out = trieMap0[ts[1]];
input = input.substring(0, i) + out + input.substring(i + ts[0]);
i += out.length - 1;
}
}
return input;
}
function trieReplace1(input) {
var len = input.length;
for (var i = 0; i < input.length; i++) {
var ts = trieSearch(input.substring(i), root1);
if (ts) {
let out = trieMap1[ts[1]];
input = input.substring(0, i) + out + input.substring(i + ts[0]);
i += out.length - 1;
}
}
return input;
}
function simpleReplace(input) {
input = trieReplace0(input);
input = input.replace(/\s/g, "");
return trieReplace1(input);
}
function parseLatexDerivatives(input){
var openPar = 1;
var parCount = 0;
var bottomStr = "";
var dx = "x";
var insideStr = "";
for (var i=0;i<input.length;i++){
if (input[i] == "{" || input[i] == "["){
openPar++;
}
else if (input[i] == "}" || input[i] == "]"){
openPar--;
if (openPar == 0){
if (parCount > 0){
bottomStr = bottomStr.substring(0,i-parCount);
if (bottomStr.substring(0,10) == "\\mathrm{d}"){
dx = bottomStr.substring(10);
insideStr = input.substring(i+2);
openPar = 0;
parCount = -1*(i+2);
}
else if (bottomStr[0] == "d"){
dx = bottomStr.substring(1);
insideStr = input.substring(i+2);
openPar = 0;
parCount = -1*(i+2);
}
else {
return "\\frac{"+input;
}
}
else if (parCount < 0){
insideStr = insideStr.substring(0,i+parCount);
input = "der("+insideStr+","+dx+")"+input.substring(i+1);
return input;
}
else {
if (input.substring(0,i) == "d" || input.substring(0,i) == "\\mathrm{d}"){
bottomStr = input.substring(i+2);
openPar = 0;
parCount = i+2;
}
else {
return "\\frac{"+input;
}
}
}
}
}
return "\\frac{"+input;
}
function parseLatexFC(input){
var openPar = 1;
var type = "floor";
if (input[0] == "⌈"){
type = "ceil";
}
for (var i=1;i<input.length;i++){
if (input[i] == "⌊"){
openPar++;
}
else if (input[i] == "⌈"){
openPar++;
}
else if (input[i] == "⌋"){
openPar--;
}
else if (input[i] == "⌉"){
openPar--;
}
if (openPar == 0){
input = type+"("+input.substring(1,i)+")"+input.substring(i+1);
return input;
}
}
return input;
}
function parseLatexRoot(input){
for (var i=0;i<input.length;i++){
if (input[i] == "]"){
if (i+1 < input.length){
if (input[i+1]=='{'){
input = "{"+input.substring(0,i)+","+input.substring(i+2);
}
else if (input[i+1]=='('){
input = "("+input.substring(0,i)+","+input.substring(i+2);
}
else {
input = input.substring(0,i)+","+input.substring(i+2);
}
}
else {
input = input.substring(0,i)+","+input.substring(i+2);
}
return input;
}
}
return input;
}
function parseLatexLog(input){
if (input.length < 2){return input;}
var pars = ["",""];
var openPar = 0;
if (input[0] == '['){
pars = ["[","]"];
openPar = 1;
}
else if (input[0] == '{'){
pars = ["{","}"];
openPar = 1;
}
else if (input[0] == '('){
pars = ["(",")"];
openPar = 1;
}
else {
if (input[0] >= "0" && input[0] <= "9"){
if (input[1]=='{'){
input = "{"+input[0]+","+input.substring(2);
}
else if (input[1]=='('){
input = "("+input[0]+","+input.substring(2);
}
else {
input = input[0]+";"+input.substring(1);
}
return input;
}
return input;
}
for (var i=1;i<input.length;i++){
if (input[i] == pars[0]){
openPar++;
}
else if (input[i] == pars[1]){
openPar--;
if (openPar == 0){
if (input[i+1]=='{'){
input = "{"+input.substring(1,i)+","+input.substring(i+2);
}
else if (input[i+1]=='('){
input = "("+input.substring(1,i)+","+input.substring(i+2);
}
else {
input = input.substring(1,i)+";"+input.substring(i+1);
}
return input;
}
}
}
return input;
}
function parseLatexMatrix(input){
var key = "";
var openPar = 1;
var idx = 0;
var val = "";
for (var i=0;i<input.length;i++){
if (input[i] == "{"){
return false;
}
else if (input[i] == "}"){
key = input.substring(0,i);
idx = i+1;
break;
}
}
var end = input.indexOf("\\end{"+key+"}");
var begin = input.indexOf("\\begin{"+key+"}",idx);
if (end < 0){
return false;
}
if (begin == -1 || begin > end){
val = input.substring(idx,end);
}
else {
return false;
}
if (key.indexOf("matrix") > -1){
var rows = val.trim().split("\\\\");
var out = "[";
for (var i=0;i<rows.length;i++){
if (rows[i].trim().length == 0){continue;}
var row = "[";
row += rows[i].trim().replace(/&/g,", ")+'';
row += "]";
if (i > 0){
out += ", ";
}
out += row;
}
out += "]";
out += input.substring(end+6+key.length);
return out;
}
return false;
}
function latexReplace(input){
for (var i=0;i<input.length;i++){
if (input[i] == "{"){
if (i >=6 && input.substring(i-6,i) == "\\begin"){
var matrix = parseLatexMatrix(input.substring(i+1));
if (matrix){
input = input.substring(0,i-6)+matrix;
}
}
else if (i >=5 && input.substring(i-5,i) == "\\frac"){
input = input.substring(0,i-5)+parseLatexDerivatives(input.substring(i+1));
}
}
else if (input[i] == "["){
if (i >=5 && input.substring(i-5,i) == "\\sqrt"){
input = input.substring(0,i-5)+"\\sqrt"+parseLatexRoot(input.substring(i+1));
}
else if (i >=4 && input.substring(i-4,i) == "sqrt"){
input = input.substring(0,i-4)+"\\sqrt"+parseLatexRoot(input.substring(i+1));
}
}
else if (input[i] == "⌊"){
input = input.substring(0,i)+parseLatexFC(input.substring(i));
}
else if (input[i] == "⌈"){
input = input.substring(0,i)+parseLatexFC(input.substring(i));
}
}
return input;
}
let trieMap0 = {};
let trieMap1 = {};
let root0 = newNode();
// Construct trie
for (var i in trieMap0){
trieInsert(i,root0);
}
let root1 = newNode();
// Construct trie
for (var i in trieMap1){
trieInsert(i,root1);
}
function newNode() {
var obj = {};
obj.isEnd = false;
obj.children = {};
return obj;
}
//Adds a key to the Trie
function trieInsert(key, pCrawl) {
let len = key.length;
var index;
for (var level = 0; level < len; level++) {
index = key[level];
if (pCrawl.children[index] == null) {
pCrawl.children[index] = newNode();
}
pCrawl = pCrawl.children[index];
}
pCrawl.isEnd = true;
}
// Returns true if key presents in trie, else false
function trieSearch(key, pCrawl) {
let len = key.length;
if (len == 0) { return; }
var index;
var longestMatch = -1;
for (var level = 0; level < len; level++) {
index = key[level];
if (pCrawl.children[index] == null) {
if (longestMatch >= 0) {
return [longestMatch + 1, key.substring(0, longestMatch + 1)];
}
else {
return false;
}
}
pCrawl = pCrawl.children[index];
if (pCrawl.isEnd) {
longestMatch = level;
}
}
if (longestMatch >= 0) {
return [longestMatch + 1, key.substring(0, longestMatch + 1)];
}
else {
return false;
}
}
function trieReplace0(input) {
var len = input.length;
for (var i = 0; i < input.length; i++) {
var ts = trieSearch(input.substring(i), root0);
if (ts) {
let out = trieMap0[ts[1]];
input = input.substring(0, i) + out + input.substring(i + ts[0]);
i += out.length - 1;
}
}
return input;
}
function trieReplace1(input) {
var len = input.length;
for (var i = 0; i < input.length; i++) {
var ts = trieSearch(input.substring(i), root1);
if (ts) {
let out = trieMap1[ts[1]];
input = input.substring(0, i) + out + input.substring(i + ts[0]);
i += out.length - 1;
}
}
return input;
}
function simpleReplace(input) {
input = trieReplace0(input);
input = input.replace(/\s/g, "");
return trieReplace1(input);
}
function parseLatexDerivatives(input){
var openPar = 1;
var parCount = 0;
var bottomStr = "";
var dx = "x";
var insideStr = "";
for (var i=0;i<input.length;i++){
if (input[i] == "{" || input[i] == "["){
openPar++;
}
else if (input[i] == "}" || input[i] == "]"){
openPar--;
if (openPar == 0){
if (parCount > 0){
bottomStr = bottomStr.substring(0,i-parCount);
if (bottomStr.substring(0,10) == "\\mathrm{d}"){
dx = bottomStr.substring(10);
insideStr = input.substring(i+2);
openPar = 0;
parCount = -1*(i+2);
}
else if (bottomStr[0] == "d"){
dx = bottomStr.substring(1);
insideStr = input.substring(i+2);
openPar = 0;
parCount = -1*(i+2);
}
else {
return "\\frac{"+input;
}
}
else if (parCount < 0){
insideStr = insideStr.substring(0,i+parCount);
input = "der("+insideStr+","+dx+")"+input.substring(i+1);
return input;
}
else {
if (input.substring(0,i) == "d" || input.substring(0,i) == "\\mathrm{d}"){
bottomStr = input.substring(i+2);
openPar = 0;
parCount = i+2;
}
else {
return "\\frac{"+input;
}
}
}
}
}
return "\\frac{"+input;
}
function parseLatexFC(input){
var openPar = 1;
var type = "floor";
if (input[0] == "⌈"){
type = "ceil";
}
for (var i=1;i<input.length;i++){
if (input[i] == "⌊"){
openPar++;
}
else if (input[i] == "⌈"){
openPar++;
}
else if (input[i] == "⌋"){
openPar--;
}
else if (input[i] == "⌉"){
openPar--;
}
if (openPar == 0){
input = type+"("+input.substring(1,i)+")"+input.substring(i+1);
return input;
}
}
return input;
}
function parseLatexRoot(input){
for (var i=0;i<input.length;i++){
if (input[i] == "]"){
if (i+1 < input.length){
if (input[i+1]=='{'){
input = "{"+input.substring(0,i)+","+input.substring(i+2);
}
else if (input[i+1]=='('){
input = "("+input.substring(0,i)+","+input.substring(i+2);
}
else {
input = input.substring(0,i)+","+input.substring(i+2);
}
}
else {
input = input.substring(0,i)+","+input.substring(i+2);
}
return input;
}
}
return input;
}
function parseLatexLog(input){
if (input.length < 2){return input;}
var pars = ["",""];
var openPar = 0;
if (input[0] == '['){
pars = ["[","]"];
openPar = 1;
}
else if (input[0] == '{'){
pars = ["{","}"];
openPar = 1;
}
else if (input[0] == '('){
pars = ["(",")"];
openPar = 1;
}
else {
if (input[0] >= "0" && input[0] <= "9"){
if (input[1]=='{'){
input = "{"+input[0]+","+input.substring(2);
}
else if (input[1]=='('){
input = "("+input[0]+","+input.substring(2);
}
else {
input = input[0]+";"+input.substring(1);
}
return input;
}
return input;
}
for (var i=1;i<input.length;i++){
if (input[i] == pars[0]){
openPar++;
}
else if (input[i] == pars[1]){
openPar--;
if (openPar == 0){
if (input[i+1]=='{'){
input = "{"+input.substring(1,i)+","+input.substring(i+2);
}
else if (input[i+1]=='('){
input = "("+input.substring(1,i)+","+input.substring(i+2);
}
else {
input = input.substring(1,i)+";"+input.substring(i+1);
}
return input;
}
}
}
return input;
}
function parseLatexMatrix(input){
var key = "";
var openPar = 1;
var idx = 0;
var val = "";
for (var i=0;i<input.length;i++){
if (input[i] == "{"){
return false;
}
else if (input[i] == "}"){
key = input.substring(0,i);
idx = i+1;
break;
}
}
var end = input.indexOf("\\end{"+key+"}");
var begin = input.indexOf("\\begin{"+key+"}",idx);
if (end < 0){
return false;
}
if (begin == -1 || begin > end){
val = input.substring(idx,end);
}
else {
return false;
}
if (key.indexOf("matrix") > -1){
var rows = val.trim().split("\\\\");
var out = "[";
for (var i=0;i<rows.length;i++){
if (rows[i].trim().length == 0){continue;}
var row = "[";
row += rows[i].trim().replace(/&/g,", ")+'';
row += "]";
if (i > 0){
out += ", ";
}
out += row;
}
out += "]";
out += input.substring(end+6+key.length);
return out;
}
return false;
}
function latexReplace(input){
for (var i=0;i<input.length;i++){
if (input[i] == "{"){
if (i >=6 && input.substring(i-6,i) == "\\begin"){
var matrix = parseLatexMatrix(input.substring(i+1));
if (matrix){
input = input.substring(0,i-6)+matrix;
}
}
else if (i >=5 && input.substring(i-5,i) == "\\frac"){
input = input.substring(0,i-5)+parseLatexDerivatives(input.substring(i+1));
}
}
else if (input[i] == "["){
if (i >=5 && input.substring(i-5,i) == "\\sqrt"){
input = input.substring(0,i-5)+"\\sqrt"+parseLatexRoot(input.substring(i+1));
}
else if (i >=4 && input.substring(i-4,i) == "sqrt"){
input = input.substring(0,i-4)+"\\sqrt"+parseLatexRoot(input.substring(i+1));
}
}
else if (input[i] == "⌊"){
input = input.substring(0,i)+parseLatexFC(input.substring(i));
}
else if (input[i] == "⌈"){
input = input.substring(0,i)+parseLatexFC(input.substring(i));
}
}
return input;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="favicon.png">
<title></title>
<meta name="description" content="" />
<style>
.output > span {
display: inline-block;
width: 2rem;
height: 1.5rem;
padding: 0.25rem 0.25rem;
text-align: center;
background: #DDD;
}
.output > span:nth-child(2n-1) {
background: #EEE;
}
div {
padding: 0;
}
.test {
border: 1px solid black;
padding: 0.5rem;
display: flex;
}
.inputHalf {
display: inline-block;
width: calc(50% - 3rem);
border-right: 1px solid black;
padding: 0.25rem;
resize:horizontal;
overflow: scroll;
}
.outputHalf {
display: inline-block;
width: calc(50% - 3rem);
padding: 0.25rem;
flex-grow: 1;
flex-shrink: 1;
}
</style>
</head>
<body>
<div>
<button onclick="fullTest()">Run Test</button>
</div>
Tests
<div>
<div class="test">
<div class="inputHalf">
<div>4x</div>
<hr />
<div>4x</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>3/2+\frac{3}{2}=0</div>
<hr />
<div>3/2+\frac{3}{2}=0</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>3/2-\frac{3}{2}=0</div>
<hr />
<div>3/2-\frac{3}{2}=0</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>math.sin(x)+Math.cos(pi)-\tan{pi/2}</div>
<hr />
<div>sin(x)+cos(pi)-\tan{pi/2}</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>Math.pow(x,2)=x**2=x^2=x^{2}</div>
<hr />
<div>pow(x,2)=x^2=x^2=x^{2}</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>Math.tan(x)*Math.sec(x)*Math.csc(x)*Math.cot(\pi)</div>
<hr />
<div>tan(x)*sec(x)*csc(x)*cot(π)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>Math.PI+Math.E</div>
<hr />
<div>π+e</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\max(1,2)</div>
<hr />
<div>max(1,2)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\pi^2</div>
<hr />
<div>π^2</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>ε^21</div>
<hr />
<div>ε^21</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\Pi*\gamma</div>
<hr />
<div>Π*γ</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>x=(-b\pm \sqrt(b^2-4*a*c))/2a</div>
<hr />
<div>x=(-b±\sqrt(b^2-4*a*c))/2a</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\sqrt[3]{x}</div>
<hr />
<div>\sqrt{3,x}</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>cos(3pi)</div>
<hr />
<div>cos(3pi)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\cos pi</div>
<hr />
<div>\cospi</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>3+infinity!=7-\infty</div>
<hr />
<div>3+∞≠7-∞</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>gcd(6,8)</div>
<hr />
<div>gcd(6,8)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>min(1+7,2*3,3+\csc x)+max(1,2)</div>
<hr />
<div>min(1+7,2*3,3+\cscx)+max(1,2)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>der(x^2+1,x)</div>
<hr />
<div>der(x^2+1,x)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>der(x^12+sin(x))=12x^11+cos(x)</div>
<hr />
<div>der(x^12+sin(x))=12x^11+cos(x)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>lim(t*sin(t),t,0,r)<=0</div>
<hr />
<div>lim(t*sin(t),t,0,r)≤0</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>lim(x+sqrt(x),x,infinity)>=0</div>
<hr />
<div></div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>12%+23%=35%</div>
<hr />
<div>12%+23%=35%</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>12%7=5</div>
<hr />
<div>12%7=5</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>6!-5! = 600</div>
<hr />
<div>6!-5!_=600</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>7 choose 3 = 7 comb 3 = comb(7,3) != 7 perm 3 = \perm(7,3)</div>
<hr />
<div>7\comb3=7\comb3=comb(7,3)≠7\perm3=\perm(7,3)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>3+\function(72*3)=1</div>
<hr />
<div>3+\function(72*3)=1</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\frac{2.3333}{3}+\frac{1}{x}=7</div>
<hr />
<div>(2.3333)/(3)+(1)/(x)=7</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\sqrt[3]{x^3-7}+sqrt[5]{x^3-8}-sqrt(3)+sqrt(x^3-7) in y</div>
<hr />
<div>\sqrt{3,x^3-7}+\sqrt{5,x^3-8}-sqrt(3)+sqrt(x^3-7)∈y</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>log(3+7)+\log{3+7}+\log 3+\log_2 3+log_2(3+7)+log_[2]{3}+log_[2](3+7)+log[2]{3+7}+log2(3+7)+log_10{3+7}</div>
<hr />
<div>log_{e}(3+7)+\log_{e}{3+7}+\log_{e}3+\log_23+log_2(3+7)+log_[2]{3}+log_[2](3+7)+log_[2]{3+7}+log_{2}(3+7)+log_{10}{3+7}</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>der(3x^12,x)=der(3x^12)=36x^11</div>
<hr />
<div>der(3x^12,x)=der(3x^12)=36x^11</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>Math.round(x/7,2)+math.round(x/7)+round(13.244,i)</div>
<hr />
<div>round(x/7,2)+round(x/7)+round(13.244,i)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>Math.floor(x/7)+math.floor(x/7)+floor(-3.27)+⌊129/17⌋-\lfloor 129/7 \rfloor=y</div>
<hr />
<div>floor(x/7)+floor(x/7)+floor(-3.27)+floor(129/17)-floor(129/7)=y</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>Math.ceil(x/7)+math.ceil(x/7)+ceil(2.9)-ceiling(-3.24)+⌈\sqrt[3]{8}⌉+\lceil sqrt(738)\rceil=y</div>
<hr />
<div>ceil(x/7)+ceil(x/7)+ceil(2.9)-ceil(-3.24)+ceil(\sqrt{3,8})+ceil(sqrt(738))=y</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>int(x^2-1,x,0,infinity)+int(x^2-1,x)+int(x^2-1,0,infinity)+int(x^2-1)</div>
<hr />
<div>int(x^2-1,x,0,∞)+int(x^2-1,x)+int(x^2-1,0,∞)+int(x^2-1)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>loglog(x)+\log\log(x)+\log \log x = 7</div>
<hr />
<div>loglog(x)+\loglog(x)+\loglogx=7</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>sum(i^2-17,i=0,infinity)!=product(i^2-17,i\in T)</div>
<hr />
<div>sum(i^2-17,i=0,∞)≠prod(i^2-17,i∈T)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>[[1,2],[3,4]]*[[5,6],[7,8]]=[[17,23],[39,53]]</div>
<hr />
<div>[[1,2],[3,4]]*[[5,6],[7,8]]=[[17,23],[39,53]]</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>6! != 5!+6</div>
<hr />
<div>6!_≠5!+6</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\lim\limits_{t\to 0^+}{t\sin{t}}</div>
<hr />
<div>lim(t*sin(t),t,0,r)≤0</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\frac{\mathrm{d}}{\mathrm{d}x}[x^2+1]</div>
<hr />
<div>der(x^2+1,x)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
<div class="test">
<div class="inputHalf">
<div>\int_{0}^{\infty} {x^2-1} \mathrm{d}{x}+\int {x^2-1} \mathrm{d}{x}</div>
<hr />
<div>int(x^2-1,x,0,∞)+int(x^2-1,x)</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
</div>
<script src="prec.js"></script>
<script src="clean.js"></script>
<script src="script.js"></script>
<script>
var els = document.querySelectorAll('.test');
function fullTest() {
for (var i=0;i<els.length;i++){
var input = els[i].querySelector('.inputHalf > div:nth-of-type(1)').textContent;
var simple = simpleReplace(input);
var latex = latexReplace(simple);
els[i].querySelector('.outputHalf > div:nth-of-type(1)').textContent = latex;
var infix = toInfixArray(latex);
var ell = els[i].querySelector('.outputHalf > div:nth-of-type(2)')
for (var ii=0;ii<infix.length;ii++){
var span = document.createElement('span');
span.textContent = infix[ii];
ell.appendChild(span);
}
var postfix = toPostfixArray(infix);
var ellp = els[i].querySelector('.outputHalf > div:nth-of-type(3)')
for (var ii=0;ii<postfix.length;ii++){
var span = document.createElement('span');
span.textContent = postfix[ii];
ellp.appendChild(span);
}
}
}
</script>
</body>
</html>
const fs = require('fs');
const express = require('express');
const nunjucks = require('nunjucks');
const app = express();
app.use('/', express.static('./'))
app.listen(3000, () => {
console.log('server started');
});
function isInt(value) {
return /^-?\d+$/.test(value);
}
function createMap(name, map, lines) {
for (var i = 0; i < lines.length; i++) {
var split = lines[i];
var out = split[1];
var outInt = parseInt(split[1]);
if (outInt && outInt < 0 && outInt >= -128) {
if (isInt(split[1])) {
out = String.fromCharCode(outInt);
}
}
if (name == "noWhitespace") {
split[0] = split[0].replace(/\s/g, "");
}
map[split[0]] = out;
if (split.length <= 2 || !split[2]) {
var lc = split[0].toLowerCase();
var uc = split[0].toUpperCase();
var cc = "";
var lastLetter = false;
for (var ii = 0; ii < split[0].length; ii++) {
var charType = "other";
var code = split[0].charCodeAt(ii);
if (code >= 'a'.charCodeAt(0) && code <= 'z'.charCodeAt(0)) {
charType = "lower";
}
if (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) {
charType = "upper";
}
if (!lastLetter && charType == "lower") {
cc += split[0].substring(ii, ii + 1).toUpperCase();
}
else {
cc += split[0].substring(ii, ii + 1);
}
if (charType == "other") {
lastLetter = false;
}
else {
lastLetter = true;
}
}
if (!map[lc]) {
map[lc] = out;
}
if (!map[uc]) {
map[uc] = out;
}
if (!map[cc]) {
map[cc] = out;
}
}
}
}
var trieMapWLines = JSON.parse(fs.readFileSync('dataW.json', 'utf8'));
var trieMapW = {};
createMap('whitespace', trieMapW, trieMapWLines);
var trieMapLines = JSON.parse(fs.readFileSync('data.json', 'utf8'));
var trieMap = {};
createMap('noWhitespace', trieMap, trieMapLines);
var trBase = fs.readFileSync('cleanTemplate.js', 'utf8');
var tr = trBase.replace('let trieMap0 = {};', 'let trieMap0 = ' + JSON.stringify(trieMapW) + ";");
var writeIt = true;
if (tr.length > trBase.length + 10) {
console.log('added trieMapW');
//console.log(trieMapW);
}
else {
console.log('failed to add trieMapW');
writeIt = false;
}
var trFinal = tr.replace('let trieMap1 = {};', 'let trieMap1 = ' + JSON.stringify(trieMap) + ";");
if (trFinal.length > tr.length + 10) {
console.log('added trieMap');
//console.log(trieMap);
}
else {
console.log('failed to add trieMap');
writeIt = false;
}
if (writeIt) {
fs.writeFileSync('clean.js', trFinal, 'utf8');
}
var testsRaw = JSON.parse(fs.readFileSync('tests.json', 'utf8'));
var tests = [];
for (var i = 0; i < testsRaw.length; i++) {
if (testsRaw[i].length < 1) { continue; }
var test = { input: testsRaw[i][0] };
if (testsRaw[i].length > 1) {
test.clean = testsRaw[i][1];
}
tests.push(test);
}
var html = nunjucks.render('template.html', { tests: tests });
fs.writeFileSync('index.html', html, 'utf8');
var prec = {};
{
prec['~'] = 100;
prec['☀'] = 100;
prec['ln'] = 100;
prec['log'] = 100;
prec['loglog'] = 100;
prec['logloglog'] = 100;
prec['matrix'] = 100;
prec['sqrt'] = 100;
prec['pow'] = 100;
prec['der'] = 100;
prec['lim'] = 100;
prec['int'] = 100;
prec['round'] = 100;
prec['floor'] = 100;
prec['ceil'] = 100;
prec['sum'] = 100;
prec['prod'] = 100;
prec['mod'] = 100;
prec['perm'] = 100;
prec['comb'] = 100;
var trig = ['sin','cos','tan','csc','sec','cot','sinh','cosh','tanh'];
var arctrig = ['arcsin','arccos','arctan','arcsinh','arccosh','arctanh'];
for (var i=0;i<trig.length;i++){
prec[trig[i]]=100;
}
for (var i=0;i<arctrig.length;i++){
prec[arctrig[i]]=100;
}
var commafns = ['max','min','gcd'];
for (var i=0;i<commafns.length;i++){
prec[commafns[i]]=100;
}
prec['!'] = 90;
prec['^'] = 80;
prec['*'] = 70;
prec['0-'] = 70;
prec['/'] = 70;
prec['frac'] = 70;
prec['+'] = 50;
prec['±'] = 50;
prec['-'] = 50;
prec['>'] = 30;
prec['<'] = 30;
prec['==='] = 30;
prec['=='] = 30;
prec['='] = 30;
prec['!=='] = 30;
prec['≠'] = 30;
prec['≤'] = 30;
prec['≥'] = 30;
prec['∈'] = 30;
prec['∉'] = 30;
prec['&'] = 20;
prec['|'] = 20;
prec[','] = 5;
prec['row'] = 5;
}
function toInfixArray(input){
var arr = [];
var str = "";
for (var i=0;i<input.length;i++){
if ("(){}[]".indexOf(input[i]) > -1){
if (str.length > 0){
if ("({[".indexOf(input[i]) > -1){
if (str[0] == "\\"){
if (prec[str.substring(1)]){
arr.push(str.substring(1));
}
else {
arr.push("\\:"+str.substring(1));
prec["\\:"+str.substring(1)]=100;
}
}
else if (isNumber(str)){
arr.push(str);
arr.push("*");
}
else if (prec[str]){
arr.push(str);
}
else {
arr.push("\\:"+str);
prec["\\:"+str]=100;
}
}
else {
arr.push(str);
}
}
arr.push(input[i]);
str = "";
}
else if (input[i] == "-"){
if (str.length > 0){arr.push(str);}
if (i == 0){
arr.push("0-");
}
else if (arr.length > 0 && prec[arr[arr.length-1]] > 0){
arr.push("0-");
}
else {
arr.push(input[i]);
}
str = "";
}
else if (input[i] == "_"){
if (str == "log"){continue;}
if (str == "" && arr.length > 0 && arr[arr.length-1] == "log"){continue;}
if (str.length > 0){arr.push(str);}
arr.push(input[i]);
str = "";
}
else if (input[i] == " "){
if (str.length > 0){arr.push(str);}
str = "";
}
else if (prec[str+input[i]]){
str += input[i];
while (i+1 < input.length && prec[str+input[i+1]]){
str += input[i+1];
i++;
}
if (str == "!" && i+1<input.length && input[i+1] == "_"){
str = "!";
i++;
}
if (str.length > 0){arr.push(str);}
str = "";
}
else if (prec[input[i]]){
if (str.length > 0){arr.push(str);}
str = "";
str += input[i];
while (i+1 < input.length && prec[str+input[i+1]]){
str += input[i+1];
i++;
}
if (str == "!" && i+1<input.length && input[i+1] == "_"){
str = "!";
i++;
}
arr.push(str);
str = "";
}
else {
str += input[i];
}
}
if (str.length > 0){arr.push(str);}
return arr;
}
function toPostfixArray(input,max=-1){
var stack = [];
var postfix = [];
var maxx = max;
if (maxx > input.length || maxx < 0){maxx = input.length;}
for (var i=0;i<maxx;i++){
if (prec[input[i]]){
if (input[i] == "frac"){input[i] = "/";}
if (stack.length == 0){
stack.push(input[i]);
}
else if (input[i] == "0-"){
stack.push(input[i]);
}
else if (prec[stack[stack.length-1]] < prec[input[i]]){
stack.push(input[i]);
}
else if (stack[stack.length-1] == "^" && input[i] == "^"){
stack.push(input[i]);
}
else {
while (stack.length > 0 && prec[stack[stack.length-1]] >= prec[input[i]]) {
if (stack[stack.length-1] == "^" && input[i] == "^"){break;}
var last = stack[stack.length-1];
if (last == "0-" && isNumber(postfix[postfix.length-1])){
postfix[postfix.length-1] = "-"+postfix[postfix.length-1];
}
else {
postfix.push(last);
}
stack.pop();
}
stack.push(input[i]);
}
}
/*else if (input[i][0] == '\\'){
stack.push(input[i]);
}*/
else if (input[i] == '(' || input[i] == '{' || input[i] == '['){
stack.push(input[i]);
}
else if (input[i] == ')'){
while (stack.length > 0 && stack[stack.length-1] != "(") {
var last = stack[stack.length-1];
if (last == "0-" && isNumber(postfix[postfix.length-1])){
postfix[postfix.length-1] = "-"+postfix[postfix.length-1];
}
else {
postfix.push(last);
}
stack.pop();
}
stack.pop();
}
else if (input[i] == '}'){
while (stack.length > 0 && stack[stack.length-1] != "{") {
var last = stack[stack.length-1];
if (last == "0-" && isNumber(postfix[postfix.length-1])){
postfix[postfix.length-1] = "-"+postfix[postfix.length-1];
}
else {
postfix.push(last);
}
stack.pop();
}
stack.pop();
}
else if (input[i] == ']'){
var isRow = false;
while (stack.length > 0 && stack[stack.length-1] != "[") {
var last = stack[stack.length-1];
if (last == ","){isRow = true;}
if (last == "0-" && isNumber(postfix[postfix.length-1])){
postfix[postfix.length-1] = "-"+postfix[postfix.length-1];
}
else {
postfix.push(last);
}
stack.pop();
}
stack.pop();
if (isRow){postfix.push("row")}
}
else {
if (input[i].length <= 1 || isNumber(input[i])){
postfix.push(input[i]);
}
else {
var idx = 1;
while (idx < input[i].length && isNumber(input[i].substring(0,idx))){
idx++;
}
if (idx > 1){
if (input[i][idx-1] == "%"){
if (idx == input[i].length){
//12% is just a number
postfix.push(input[i]);
}
else {
//12%7 becomes 12mod7
input.splice(i,1,input[i].substring(0,idx-1),"mod",input[i].substring(idx));
maxx = max;
if (maxx > input.length || maxx < 0){maxx = input.length;}
i--;
continue;
}
}
else {
//Converts 4x to 4*x
input.splice(i,1,input[i].substring(0,idx-1),"*",input[i].substring(idx-1));
maxx = max;
if (maxx > input.length || maxx < 0){maxx = input.length;}
i--;
continue;
}
}
else {
postfix.push(input[i]);
}
}
}
}
if (max == -1){
while (stack.length > 0) {
var last = stack[stack.length-1];
if (last == "0-" && isNumber(postfix[postfix.length-1])){
postfix[postfix.length-1] = "-"+postfix[postfix.length-1];
}
else {
postfix.push(last);
}
stack.pop();
}
return postfix;
}
return {postfix:postfix,stack:stack};
}
function newInput(input){
var arr = toInfixArray(input);
var postfix = toPostfixArray(arr,-1);
console.log(postfix)
var out = document.getElementById('infixArray');
out.innerHTML = "";
for (var i=0;i<arr.length;i++){
var span = document.createElement('span');
span.textContent = arr[i];
out.appendChild(span);
}
out = document.getElementById('postfixArray');
out.innerHTML = "";
for (var i=0;i<postfix.length;i++){
var span = document.createElement('span');
span.textContent = postfix[i];
out.appendChild(span);
}
var allSteps = document.getElementById('allSteps');
allSteps.innerHTML = "";
for (var ii=1;ii<arr.length+1;ii++){
var obj = toPostfixArray(arr,ii);
var tr = document.createElement('tr');
var cell1 = document.createElement('td');
cell1.textContent = arr[ii-1];
tr.appendChild(cell1);
var cell2 = document.createElement('td');
cell2.classList.add('output');
var cell3 = document.createElement('td');
cell3.classList.add('output');
tr.appendChild(cell2);
tr.appendChild(cell3);
for (var i=0;i<obj.postfix.length;i++){
var span = document.createElement('span');
span.textContent = obj.postfix[i];
cell2.appendChild(span);
}
for (var i=0;i<obj.stack.length;i++){
var span = document.createElement('span');
span.textContent = obj.stack[i];
cell3.appendChild(span);
}
allSteps.appendChild(tr);
}
}
function isNumber(input){
var len = input.length;
if (len == 0){return false;}
for (var i=0;i<len;i++){
if ("0123456789.".indexOf(input[i]) < 0){
return false;
}
}
return true;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="favicon.png">
<title></title>
<meta name="description" content="" />
<style>
.output > span {
display: inline-block;
width: 2rem;
height: 1.5rem;
padding: 0.25rem 0.25rem;
text-align: center;
background: #DDD;
}
.output > span:nth-child(2n-1) {
background: #EEE;
}
div {
padding: 0;
}
.test {
border: 1px solid black;
padding: 0.5rem;
display: flex;
}
.inputHalf {
display: inline-block;
width: calc(50% - 3rem);
border-right: 1px solid black;
padding: 0.25rem;
resize:horizontal;
overflow: scroll;
}
.outputHalf {
display: inline-block;
width: calc(50% - 3rem);
padding: 0.25rem;
flex-grow: 1;
flex-shrink: 1;
}
</style>
</head>
<body>
<div>
<button onclick="fullTest()">Run Test</button>
</div>
Tests
<div>
{% for item in tests %}
<div class="test">
<div class="inputHalf">
<div>{{item['input']}}</div>
<hr />
<div>{{item['clean']}}</div>
</div>
<div class="outputHalf">
<div></div>
<hr />
<div class="output"></div>
<hr />
<div class="output"></div>
</div>
</div>
{% endfor %}
</div>
<script src="prec.js"></script>
<script src="clean.js"></script>
<script src="script.js"></script>
<script>
var els = document.querySelectorAll('.test');
function fullTest() {
for (var i=0;i<els.length;i++){
var input = els[i].querySelector('.inputHalf > div:nth-of-type(1)').textContent;
var simple = simpleReplace(input);
var latex = latexReplace(simple);
els[i].querySelector('.outputHalf > div:nth-of-type(1)').textContent = latex;
var infix = toInfixArray(latex);
var ell = els[i].querySelector('.outputHalf > div:nth-of-type(2)')
for (var ii=0;ii<infix.length;ii++){
var span = document.createElement('span');
span.textContent = infix[ii];
ell.appendChild(span);
}
var postfix = toPostfixArray(infix);
var ellp = els[i].querySelector('.outputHalf > div:nth-of-type(3)')
for (var ii=0;ii<postfix.length;ii++){
var span = document.createElement('span');
span.textContent = postfix[ii];
ellp.appendChild(span);
}
}
}
</script>
</body>
</html>
const fs = require('fs');
const { GoogleSpreadsheet } = require('google-spreadsheet');
async function loadSheets() {
const doc = new GoogleSpreadsheet('1W3wwOlcgemhS3_4Phd5D1gWR70dn27MJZNCABw0CJu8');
//you will need to create your own Google API token w/ Sheets access
let token = fs.readFileSync('token.json',{encoding:'utf8'});
await doc.useServiceAccountAuth(JSON.parse(token));
await doc.loadInfo();
console.log(doc.title);
const sheet = doc.sheetsByIndex[0];
const rows = await sheet.getRows();
console.log(sheet.headerValues);
var dataW = [];
for (var i=0;i<rows.length;i++){
dataW.push(rows[i]._rawData);
}
fs.writeFileSync("dataW.json",JSON.stringify(dataW));
const sheet1 = doc.sheetsByIndex[1];
const rows1 = await sheet1.getRows();
console.log(sheet1.headerValues);
var data = [];
for (var i=0;i<rows1.length;i++){
data.push(rows1[i]._rawData);
}
fs.writeFileSync("data.json",JSON.stringify(data));
const sheet2 = doc.sheetsByIndex[2];
const rows2 = await sheet2.getRows();
console.log(sheet2.headerValues);
var data = [];
for (var i=0;i<rows2.length;i++){
data.push(rows2[i]._rawData);
}
fs.writeFileSync("tests.json",JSON.stringify(data));
}
loadSheets()
This repl tests how math expressions are cleaned and postfixed.
To view this on TripleLog, click here
The updateSheet.js file reads some data from a Google Sheet. You will need to add authentication to run this update. If you don't want/need to do this, then it is not necessary. Create the API account if you haven't already and add a service worker account key. View the google-spreadsheet documentation to get started. Read my blog post about how to convert a Google Sheet to an HTML table.
There are 3 sheets in the spreadsheet: one for expressions to replace before whitespace is removed, one for after, and then a sheet of tests.
The index.html is a generated file so if you change it then your changes will be overwritten. Edit the template.html file. When you click the run test button, all of the inputs are cleaned and postfixed.
The left side includes the original input and the (usually) correct cleaned version. The right side will then include the tested cleaned version, the infix array, and the postfix array.
The JavaScript is includes several files to convert the strings.
The index.js file reads the 3 json files and modifies the clean js file and generates the index.html file.
If you change the data or test jsons or the template.html you will need to rerun the index.js file.