<!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>
#message {
padding: 0 0.5rem;
border: 2px solid green;
}
</style>
</head>
<body onload="updateTree()">
<div >
<div style="max-width: 100ch; padding-bottom: 0.5rem;">
Start typing a Python/JavaScript/LaTeX math expression in the box below. The tree will be pruned to show the strings that are possible. Nodes with green backgrounds are the ends of a string. Click an ending node to see the replacement.
</div>
<div>
Input: <input type="text" value="\p" id="trieInput" oninput="updateTree()" />
Replacement: <span id="message"></span>
</div>
<svg id="tree" style="width: 100%;" viewBox="-10 -10 900 450">
<g class="links"></g>
<g class="nodes"></g>
</svg>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="script.js"></script>
</body>
</html>
var wordsMap = {"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":"ω"};
function newTrie(words){
let root = newNode();
// Construct trie
for (var i in words){
var word = words[i];
trieInsert(word,root);
}
//console.log(root);
return root;
}
function trieToTree(trie,key){
//console.log(key);
if (!trie.children){
if (trie.isEnd){
return {'letter':key,'isEnd':trie.isEnd};
}
else {
return {'letter':key,'isEnd':false};
}
}
var children = [];
for (var c in trie.children){
children.push(trieToTree(trie.children[c],c));
}
if (children.length == 0){
if (trie.isEnd){
return {'letter':key,'isEnd':trie.isEnd};
}
else {
return {'letter':key,'isEnd':false};
}
}
if (key){
if (trie.isEnd){
return {'letter':key,'isEnd':trie.isEnd,children:children};
}
else {
return {'letter':key,'isEnd':false,children:children};
}
}
else {
return {children:children};
}
}
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 = key;
}
var nodes;
function updateTree(){
var str = document.getElementById('trieInput').value;
var words = [];
for (var i in wordsMap){
if (i.substring(0,str.length) == str){
words.push(i);
}
}
var trie = newTrie(words);
var trieTree = trieToTree(trie,false);
//console.log(flare);
var root = d3.hierarchy(trieTree);
//console.log(root);
var treeLayout = d3.tree()
.size([430, 880]);
treeLayout(root);
var svgLinks = document.querySelector('#tree g.links')
svgLinks.innerHTML = "";
var svgNodes = document.querySelector('#tree g.nodes')
svgNodes.innerHTML = "";
var links = root.links();
nodes = root.descendants();
for (var el in links){
if (links[el].source.y == 0){continue;}
var link = document.createElementNS("http://www.w3.org/2000/svg",'line');
link.setAttributeNS(null,'x1',links[el].source.y);
link.setAttributeNS(null,'y1',links[el].source.x);
link.setAttributeNS(null,'x2',links[el].target.y);
link.setAttributeNS(null,'y2',links[el].target.x);
link.setAttributeNS(null,'stroke',"darkgray");
link.setAttributeNS(null,'stroke-width',"2");
svgLinks.appendChild(link);
}
for (var el in nodes){
if (nodes[el].y == 0){continue;}
var node = document.createElementNS("http://www.w3.org/2000/svg",'circle');
node.setAttributeNS(null,'cx',nodes[el].y);
node.setAttributeNS(null,'cy',nodes[el].x);
node.setAttributeNS(null,'r',"10");
if (nodes[el].data.isEnd){
node.setAttributeNS(null,'fill',"#9F9");
node.setAttributeNS(null,'stroke-width',"2");
node.id = "node-"+el;
node.style.cursor = "pointer";
node.addEventListener('click',showLabel);
node.addEventListener('pointerenter',showLabel);
}
else {
node.setAttributeNS(null,'fill',"lightblue");
}
node.setAttributeNS(null,'stroke',"darkgray");
node.setAttributeNS(null,'stroke-width',"1");
svgNodes.appendChild(node);
if (nodes[el].data.letter){
var label = document.createElementNS("http://www.w3.org/2000/svg",'text');
label.setAttributeNS(null,'x',nodes[el].y);
label.setAttributeNS(null,'y',nodes[el].x+4);
label.setAttributeNS(null,'text-anchor',"middle");
label.setAttributeNS(null,'fill',"black");
label.style.pointerEvents = "none";
label.innerHTML = nodes[el].data.letter;
svgNodes.appendChild(label);
}
}
}
function showLabel(evt){
if (!evt.currentTarget.id){return;}
var id = evt.currentTarget.id.substring(5);
var el = document.getElementById('message');
var key = nodes[id].data.isEnd;
var val = wordsMap[key];
el.textContent = key + " => " + val;
}
This repl creates a tree that is pruned to only show the possible completions of the inputted text.
To view this on TripleLog, click here.
The HTML is a simple input to change a string of text with an SVG that displays the trie tree.
Add CSS by editing the style.css file that is linked to in the head section or inline edit the style section in the head.
The script.js file generates a trie and converts it to a D3 tree. Then as the user types, the tree is pruned to eliminate the strings that are no longer possible.
Edit the wordsMap json object to change the list of strings to search for.