<!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>
div {
padding: 1rem;
}
</style>
</head>
<body>
<div>
Input String: <input type="text" style="width: 20rem;" value="" oninput="outputEl.textContent = simpleReplace(this.value);" onchange="outputEl.textContent = simpleReplace(this.value);" />
</div>
<div>
Output: <span id="output"></span>
</div>
<div>
Enter a string in the input above and it be converted into a slightly different format.
</div>
<script>
var outputEl = document.getElementById('output');
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);
}
</script>
</body>
</html>
const fs = require('fs');
const express = require('express');
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('template.html', '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('index.html',trFinal, 'utf8');
}
<!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>
div {
padding: 1rem;
}
</style>
</head>
<body>
<div>
Input String: <input type="text" style="width: 20rem;" value="" oninput="outputEl.textContent = simpleReplace(this.value);" onchange="outputEl.textContent = simpleReplace(this.value);" />
</div>
<div>
Output: <span id="output"></span>
</div>
<div>
Enter a string in the input above and it be converted into a slightly different format.
</div>
<script>
var outputEl = document.getElementById('output');
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);
}
</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));
}
loadSheets()
This repl cleans up many math expressions to make them simpler to postfix. Read this blog post for more information.
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.
The index.html is a generated file so if you change it then your changes will be overwritten. Edit the template.html file. The HTML part is a very simple input/output. Then there is a lot of inline JS. You can improve the HTML to do more if you have ideas.
The JavaScript is included in the template.html file and performs a couple of trie search and replaces. You can generate a separate JS file if you wish.
A trie is created to replace some strings that have important whitespace. Then whitespace is replaced. Then another trie replaces lots more strings. Changing the data maps either by using different spreadsheets or by changing the data files will change the replacements.
The index.js file reads the 2 json files and inserts them into the template file. Then the index.html is generated.
The generated (index.html) file is a static file so it can be served by your preferred method of serving static files.