How to reverse Javascript XOR and AND bitwise Operators - javascript

I have this code in JS:
function test(e) {
for (var t = "", n = e.charCodeAt(0), i = 1; i < e.length; ++i) {
t += String.fromCharCode(e.charCodeAt(i) ^ i + n & 127);
}
return t;
}
console.log(test('#\f+ 6*5(.=j\x02"9+=>4&s\x11-&;7+?)'));
Console Output is: Microsoft Internet Explorer
Is it possible to reverse a function to do the opposite?
When I write:
console.log(test('Microsoft Internet Explorer'));
I need: #\f+ 6*5(.=j\x02"9+=>4&s\x11-&;7+?)

Your code uses the first character code to XOR the other characters codes. So you can't simply reverse it since it expects 2 inputs. Not just the content string, but also the character that is used for the XOR operation. You can't guess this to be the # since all characters are valid, but produce different encrypted stings.
XOR is the reverse of itself, similar to how multiplying with -1 is the reverse of itself. This means you can re-use a single function for encryption and decryption. The only thing left to do is add the key character at the front for encryption, and remove it for decryption.
This is not code golf, so I've chose some more sensible names (mainly e, t and n are confusing). In my opinion good variable names help readers understand the code better.
function toggleEncryption(keyChar, string) {
const keyCode = keyChar.charCodeAt(0);
let result = "";
for (let index = 0; index < string.length; ++index) {
const code = string.charCodeAt(index);
result += String.fromCharCode(code ^ index + 1 + keyCode & 127);
}
return result;
}
function decrypt(encryptedString) {
return toggleEncryption(encryptedString[0], encryptedString.slice(1));
}
function encrypt(keyChar, string) {
return keyChar[0] + toggleEncryption(keyChar, string);
}
const string = "Microsoft Internet Explorer";
console.log(string);
const encrypted = encrypt("#", string);
console.log(encrypted);
const decrypted = decrypt(encrypted);
console.log(decrypted);
console.log(string == decrypted);
console.log(encrypted == '#\f+ 6*5(.=j\x02"9+=>4&s\x11-&;7+?)');
// Like I said in the introduction you could replace the # with
// any character, but this will produce a different encrypted
// string.
const encrypted2 = encrypt("!", string);
console.log(encrypted2);
const decrypted2 = decrypt(encrypted2);
console.log(decrypted2);
Non-printable characters are not displayed inside the Stack Overflow snippet, but most browsers do show them in the browser console. For most browsers press Ctrl + Shift + I or F12 to open up developer tools and select the console.
It's important to note the operator precedence of:
code ^ index + 1 + keyCode & 127
// is executed as:
code ^ ((index + 1 + keyCode) & 127)
This means that only the XOR operator is called upon code and that is the only thing that has to be reversed.

function test(e) {
for (var t = "", n = e.charCodeAt(0), i = 1; i < e.length; ++i) {
t += String.fromCharCode(e.charCodeAt(i) ^ i - n & 127);
}
return t;
}
Look at - here:
t += String.fromCharCode(e.charCodeAt(i) ^ i - n & 127);
^

Bitwise & operation cannot be reversed :
0 & 1 = 0;
0 & 0 = 0;

Related

Equivalent of Swift &+ in JavaScript

I'm not able to get the same djbhash in JavaScript that I was getting in Swift.
extension String {
public func djbHash() -> Int {
return self.utf8
.map {return $0}
.reduce(5381) {
let h = ($0 << 5) &+ $0 &+ Int($1)
print("h", h)
return h
}
}
}
var djbHash = function (string) {
var h = 5381; // our hash
var i = 0; // our iterator
for (i = 0; i < string.length; i++) {
var ascii = string.charCodeAt(i); // grab ASCII integer
h = (h << 5) + h + ascii; // bitwise operations
}
return h;
}
I tried using BigInt, but the value for the string "QHChLUHDMNh5UTBUcgtLmlPziN42" I'm getting is 17760568308754997342052348842020823769412069976n, compared to 357350748206983768 in Swift.
The Swift &+ operator is an “overflow operator”: It truncates the result of the addition to the available number of bits for the used integer type.
A Swift Int is a 64-bit (signed) integer on all 64-bit platforms, and adding two integers would crash with a runtime exception if the result does not fit into an Int:
let a: Int = 0x7ffffffffffffff0
let b: Int = 0x7ffffffffffffff0
print(a + b) // 💣 Swift runtime failure: arithmetic overflow
With &+ the result is truncated to 64-bit:
let a: Int = 0x7ffffffffffffff0
let b: Int = 0x7ffffffffffffff0
print(a &+ b) // -32
In order to get the same result with JavaScript and BigInt one can use the BigInt.asIntN() function:
var a = 0x7ffffffffffffff0n
var b = 0x7ffffffffffffff0n
console.log(a + b) // 18446744073709551584n
console.log(BigInt.asIntN(64, a+b)) // -32n
With that change, the JavaScript function gives the same result as your Swift code:
var djbHash = function (string) {
var h = 5381n; // our hash
var i = 0; // our iterator
for (i = 0; i < string.length; i++) {
var code = string.charCodeAt(i); // grab UTF-16 code point
h = BigInt.asIntN(64, (h << 5n) + h + BigInt(code)); // bitwise operations
}
return h;
}
console.log(djbHash("QHChLUHDMNh5UTBUcgtLmlPziN42")) // 357350748206983768n
As mentioned in the comments to the other answer, charCodeAt() returns UTF-16 code points, whereas your Swift function works with the UTF-8 representation of a string. So this will still give different results for strings containing any non-ASCII characters.
For identical results for arbitrary strings (umlauts, Emojis, flags, ...) its best to work with the Unicode code points. In Swift that would be
extension String {
public func djbHash() -> Int {
return self.unicodeScalars
.reduce(5381) { ($0 << 5) &+ $0 &+ Int($1.value) }
}
}
print("äöü€😀🚩".djbHash()) // 6958626281456
(You may also consider to use Int64 instead of Int for platform-independent code, or Int32 if a 32-bit hash is sufficient.)
The corresponding JavaScript code is
var djbHash = function (string) {
var h = 5381n; // our hash
for (const codePoint of string) {
h = BigInt.asIntN(64, (h << 5n) + h + BigInt(codePoint.codePointAt(0))); // bitwise operations
}
return h;
}
console.log(djbHash("äöü€😀🚩")) // 6958626281456n
I've had a similar issue in which I've used the & in combination with the used operator. I think the code below should work. It's still under review but you can checkout my post
var djbHash = function (string) {
var h = 5381; // our hash
var i = 0; // our iterator
for (i = 0; i < string.length; i++) {
var ascii = string.charCodeAt(i); // grab ASCII integer
h = (h << 5) + h &+ ascii; // bitwise operations
}
return h;
}

How do get input 2^3 to Math.pow(2, 3)?

I have this simple calculator script, but it doesn't allow power ^.
function getValues() {
var input = document.getElementById('value').value;
document.getElementById('result').innerHTML = eval(input);
}
<label for="value">Enter: </label><input id="value">
<div id="result">Results</div>
<button onclick="getValues()">Get Results</button>
I tried using input = input.replace( '^', 'Math.pow(,)');
But I do not know how to get the values before '^' and after into the brackets.
Example: (1+2)^3^3 should give 7,625,597,484,987
Use a regular expression with capture groups:
input = '3 + 2 ^3';
input = input.replace(/(\d+)\s*\^\s*(\d+)/g, 'Math.pow($1, $2)');
console.log(input);
This will only work when the arguments are just numbers. It won't work with sub-expressions or when you repeat it, like
(1+2)^3^3
This will require writing a recursive-descent parser, and that's far more work than I'm willing to put into an answer here. Get a textbook on compiler design to learn how to do this.
I don't think you'll be able to do this with simple replace.
If you want to parse infix operators, you build two stacks, one for symbols, other for numbers. Then sequentially walk the formula ignoring everything else than symbols, numbers and closing parenthesis. Put symbols and numbers into their stacks, but when you encounter closing paren, take last symbol and apply it to two last numbers. (was invented by Dijkstra, I think)
const formula = '(1+2)^3^3'
const symbols = []
const numbers = []
function apply(n2, n1, s) {
if (s === '^') {
return Math.pow(parseInt(n1, 10), parseInt(n2, 10))
}
return eval(`${n1} ${s} ${n2}`)
}
const applyLast = () => apply(numbers.pop(), numbers.pop(), symbols.pop())
const tokenize = formula => formula.split(/(\d+)|([\^\/\)\(+\-\*])/).filter(t => t !== undefined && t !== '')
const solver = (formula) => {
const tf = tokenize(formula)
for (let l of formula) {
const parsedL = parseInt(l, 10)
if (isNaN(parsedL)) {
if (l === ')') {
numbers.push(applyLast())
continue
} else {
if (~['+', '-', '*', '/', '^'].indexOf(l))
symbols.push(l)
continue
}
}
numbers.push(l)
}
while (symbols.length > 0)
numbers.push(applyLast())
return numbers.pop()
}
console.log(solver(formula))
Get your input into a string and do...
var input = document.getElementById('value').value;
var values = input.split('^'); //will save an array with [value1, value 2]
var result = Math.pow(values[0], values[1]);
console.log(result);
This only if your only operation is a '^'
EDIT: Saw example after edit, this no longer works.
function getValues() {
var input = document.getElementById('value').value;
// code to make ^ work like Math.pow
input = input.replace( '^', '**');
document.getElementById('result').innerHTML = eval(input);
}
The ** operator can replace the Math.pow function in most modern browsers. The next version of Safari (v10.1) coming out any day supports it.
As said in other answers here, you need a real parser to solve this correctly. A regex will solve simple cases, but for nested statements you need a recursive parser. For Javascript one library that offers this is peg.js.
In your case, the example given in the online version can be quickly extended to handle powers:
Expression
= head:Term tail:(_ ("+" / "-") _ Term)* {
var result = head, i;
for (i = 0; i < tail.length; i++) {
if (tail[i][1] === "+") { result += tail[i][3]; }
if (tail[i][1] === "-") { result -= tail[i][3]; }
}
return result;
}
Term
= head:Pow tail:(_ ("*" / "/") _ Pow)* { // Here I replaced Factor with Pow
var result = head, i;
for (i = 0; i < tail.length; i++) {
if (tail[i][1] === "*") { result *= tail[i][3]; }
if (tail[i][1] === "/") { result /= tail[i][3]; }
}
return result;
}
// This is the new part I added
Pow
= head:Factor tail:(_ "^" _ Factor)* {
var result = 1;
for (var i = tail.length - 1; 0 <= i; i--) {
result = Math.pow(tail[i][3], result);
}
return Math.pow(head, result);
}
Factor
= "(" _ expr:Expression _ ")" { return expr; }
/ Integer
Integer "integer"
= [0-9]+ { return parseInt(text(), 10); }
_ "whitespace"
= [ \t\n\r]*
It returns the expected output 7625597484987 for the input string (1+2)^3^3.
Here is a Python-based version of this question, with solution using pyparsing: changing ** operator to power function using parsing?

Using two for loops to compare two strings

I am working through exercises on exercism.io and the third one asks us to compare two DNA strings and return the difference (hamming distance) between them.
So for example:
GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^ ^ ^ ^^
There are 7 different characters lined up in that comparison. My question is whether I'm taking the right approach to solve this. I created two empty arrays, created a function that loops through both strings and pushes the different letters when they meet.
I tried running it through a console and I always get an unexpected input error.
var diff = [];
var same = [];
function ham(dna1, dna2) {
for (var i = 0; i < dna1.length; i++)
for (var j = 0; j < dna2.length; i++){
if (dna1[i] !== dna2[j]) {
console.log(dna1[i]);
diff.push(dna1[i]);
}
else {
console.log(dna1[i]);
same.push(dna1[i]);
}
return diff.length;
}
ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff.length + ".");
Do not use globals.
Do not use nested loops if you don't have to.
Do not store useless things in arrays.
function ham(dna1, dna2) {
if (dna1.length !== dna2.length) throw new Error("Strings have different length.");
var diff = 0;
for (var i = 0; i < dna1.length; ++i) {
if (dna1[i] !== dna2[i]) {
++diff;
}
}
return diff;
}
var diff = ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff + ".");
The first problem is that you're missing a closing }. I think you want it right before the return statement.
secondly, there's a problem with your algorithm. You compare every item in dna1 (i) with every item in dna2 instead of coparing the item in the same position.
To use a shorter example so we can step through it, consider comparing 'CAT' and 'CBT'. you want to compare the characters in the same position in each string. So you don't actually want 2 for loops, you only want 1. You'd compare C to C ([0]), A to B ([1]), and T to T ( [2] ) to find the 1 difference at [1]. Now step through that with your 2 for loops in your head, and you'll see that you'll get many more differences than exist.
Once you use the same offset for the characters in each string to compare, you have to stat worrying that one might be shorter than the other. You'll get an error if you try to use an offset at the end of the string. So we have to take that into account too, and assumedly count the difference between string length as differences. But perhaps this is out of scope for you, and the the strings will always be the same.
You only need to have one single loop like below:
var diff = [];
var same = [];
function ham(dna1, dna2) {
for (var i = 0; i < dna1.length; i++) {
if (dna1[i] !== dna2[i]) {
console.log("not same");
diff.push(dna1[i]);
} else {
console.log("same");
same.push(dna1[i]);
}
}
return diff.length;
}
ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff.length + ".");
The edit distance is not really hard to calculate. More code is needed to cover the edge cases in parameter values.
function hamming(str1, str2) {
var i, len, distance = 0;
// argument validity check
if (typeof str1 === "undefined" || typeof str2 === "undefined") return;
if (str1 === null || str2 === null) return;
// all other argument types are assumed to be meant as strings
str1 = str1.toString();
str2 = str2.toString();
// the longer string governs the maximum edit distance
len = str1.length > str2.length ? str1.length : str2.length;
// now we can compare
for (i = 0; i < len; i++) {
if ( !(str1[i] === str2[i]) ) distance++;
}
return distance;
}
Execution of function:
ham( "GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT" );
of the following function definition:
function ham(A,B){
var D = [], i = 0;
i = A.length > B.length ? A : B;
for( var x in i)
A[x] == B[x] ? D.push(" ") : D.push("^");
console.log( A + "\n" + B +"\n" + D.join("") );
}
will output the log of:
GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^ ^ ^ ^^
Is capable of receiving different length strings, which depending on the requirement and data representation comparison can be modified to fill the blank with adequate standard symbols etc.
Demo:
ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
function ham(A, B) {
var D = [],
i = 0;
i = A.length > B.length ? A : B;
for (var x in i)
A[x] == B[x] ? D.push(" ") : D.push("^");
console.log(A + "\n" + B + "\n" + D.join(""));
};
I think that you would want to do something like this:
var dna1 = "GAGCCTACTAACGGGAT";
var dna2 = "CATCGTAATGACGGCCT";
function ham(string1, string2) {
var counter = 0;
for (i = 0;i < string1.length;i++) {
if (string1.slice(i, i + 1) != string2.slice(i, i + 1)) {
counter++
};
};
return(counter);
};
console.log("insert text here " + ham(dna1, dna2));
It checks each character of the string against the corresponding character of the other string, and adds 1 to the counter whenever the 2 characters are not equal.
You can use Array#reduce to iterate the 1st string, by using Function#call, and compare each letter to the letter of the corresponding index in the 2nd string.
function ham(dna1, dna2) {
return [].reduce.call(dna1, function(count, l, i) {
return l !== dna2[i] ? count + 1 : count;
}, 0);
}
var diff =ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff + ".");

Longitudinal redundancy check in Javascript

I'm working with a system that integrates a Point of Sell (POS) device, I use chrome serial to scan ports and be able to read credit card data.
The problem I'm facing is that I need to concat the LRC from a string in this format:
STX = '\002' (2 HEX) (Start of text)
LLL = Length of data (doesn't include STX or ETX but command).
Command C50 {C = A message from PC to POS, 50 the actual code that "prints" a message on POS}
ETX = '\003' (3 HEX) (End of text)
LRC = Longitudinal Redundancy Check
A message example would be as follows:
'\002014C50HELLO WORLD\003'
Here we can see 002 as STX, 014 is the length from C50 to D, and 003 as ETX.
I found some algorithms in C# like this one or this one and even this one in Java, I even saw this question that was removed from SO on Google's cache, which actually asks the same as I but had no examples or answers.
I also made this Java algorithm:
private int calculateLRC(String str) {
int result = 0;
for (int i = 0; i < str.length(); i++) {
String char1 = str.substring(i, i + 1);
char[] char2 = char1.toCharArray();
int number = char2[0];
result = result ^ number;
}
return result;
}
and tried passing it to Javascript (where I have poor knowledge)
function calculateLRC2(str) {
var result = 0;
for (var i = 0; i < str.length; i++) {
var char1 = str.substring(i, i + 1);
//var char2[] = char1.join('');
var number = char1;
result = result ^ number;
}
return result.toString();
}
and after following the Wikipedia's pseudocode I tried doing this:
function calculateLRC(str) {
var buffer = convertStringToArrayBuffer(str);
var lrc;
for (var i = 0; i < str.length; i++) {
lrc = (lrc + buffer[i]) & 0xFF;
}
lrc = ((lrc ^ 0xFF) + 1) & 0xFF;
return lrc;
}
This is how I call the above method:
var finalMessage = '\002014C50HELLO WORLD\003'
var lrc = calculateLRC(finalMessage);
console.log('lrc: ' + lrc);
finalMessage = finalMessage.concat(lrc);
console.log('finalMessage: ' + finalMessage);
However after trying all these methods, I still can't send a message to POS correctly. I have 3 days now trying to fix this thing and can't do anything more unless I finish it.
Is there anyone that knows another way to calculate LRC or what am I doing wrong here? I need it to be with Javascritpt since POS comunicates with PC through NodeJS.
Oh btw the code from convertStringToArrayBuffer is on the chrome serial documentation which is this one:
var writeSerial=function(str) {
chrome.serial.send(connectionId, convertStringToArrayBuffer(str), onSend);
}
// Convert string to ArrayBuffer
var convertStringToArrayBuffer=function(str) {
var buf=new ArrayBuffer(str.length);
var bufView=new Uint8Array(buf);
for (var i=0; i<str.length; i++) {
bufView[i]=str.charCodeAt(i);
}
return buf;
}
Edit After testing I came with this algorithm which returns a 'z' (lower case) with the following input: \002007C50HOLA\003.
function calculateLRC (str) {
var bytes = [];
var lrc = 0;
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
for (var i = 0; i < str.length; i++) {
lrc ^= bytes[i];
console.log('lrc: ' + lrc);
//console.log('lrcString: ' + String.fromCharCode(lrc));
}
console.log('bytes: ' + bytes);
return String.fromCharCode(lrc);
}
However with some longer inputs and specialy when trying to read card data, LRC becomes sometimes a Control Character which in my case that I use them on my String, might be a problem. Is there a way to force LRC to avoid those characters? Or maybe I'm doing it wrong and that's why I'm having those characters as output.
I solved LRC issue by calculating it with the following method, after reading #Jack A.'s answer and modifying it to this one:
function calculateLRC (str) {
var bytes = [];
var lrc = 0;
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
for (var i = 0; i < str.length; i++) {
lrc ^= bytes[i];
}
return String.fromCharCode(lrc);
}
Explanation of what it does:
1st: it converts the string received to it's ASCII equivalent (charCodeAt()).
2nd: it calculates LRC by doing a XOR operation between last calculated LRC (0 on 1st iteration) and string's ASCII for each char.
3rd: it converts from ASCII to it's equivalent chat (fromCharCode()) and returns this char to main function (or whatever function called it).
Your pseudocode-based algorithm is using addition. For the XOR version, try this:
function calculateLRC(str) {
var buffer = convertStringToArrayBuffer(str);
var lrc = 0;
for (var i = 0; i < str.length; i++) {
lrc = (lrc ^ buffer[i]) & 0xFF;
}
return lrc;
}
I think your original attempt at the XOR version was failing because you needed to get the character code. The number variable still contained a string when you did result = result ^ number, so the results were probably not what you expected.
This is a SWAG since I don't have Node.JS installed at the moment so I can't verify it will work.
Another thing I would be concerned about is character encoding. JavaScript uses UTF-16 for text, so converting any non-ASCII characters to 8-bit bytes may give unexpected results.

Converting exponential LaTeX syntax to PHP's pow() using JavaScript

I would like to use JS to convert a nested exponential LaTeX expression such as
2^{3^{4^5}}
to PHP's pow() syntax
pow(2,pow(3,pow(4,5)))
I know JS doesn't support recursive RegExp. The expression is part of an equation, so I expect the solution to work with something like
\frac{3}{9}+\frac{2^{\sqrt{4^2}}}{6}
which should output
\frac{3}{9}+\frac{pow(2,\sqrt{pow(4,2)})}{6}
like in #AbcAeffchen's solution.
I don't need conversion for the non-exponential parts.
Notice: The solution must not require resorting to PHP 5.6, which introduced the ** operator
An ugly hack,
> foo
'2,(3^(4^5))'
> var foo = "2^(3^(4^5))".replace(/\^/g, ",");
undefined
> foo
'2,(3,(4,5))'
> var bar = foo.replace(/(\d,)(?=[^\d])/g, "$1pow");
undefined
> var foobar = bar.replace(/^(.*)$/, "pow($1)")
undefined
> foobar
'pow(2,pow(3,pow(4,5)))'
Try this function I wrote. It just uses ordinary string functions, so it is a little bit longer.
Basically it works as the following
find the first occurrence of ^
find the part before ^ that belongs to the basis
find the part after ^ that belongs to the exponent
call the function recursive on the exponent and on the part after the exponent
put all parts together.
and so it looks in JavaScript:
function convertLatexPow(str)
{
// contains no pow
var posOfPow = str.indexOf('^');
if(posOfPow == -1)
return str;
var head = str.substr(0,posOfPow);
var tail = str.substr(posOfPow+1);
// find the beginning of pow
var headLen = posOfPow;
var beginning = 0;
var counter;
if(head[headLen-1] == '}') // find the opening brace
{
counter = 1;
for(i = headLen-2; i >= 0; i--)
{
if(head[i] == '}')
counter++;
else if(head[i] == '{')
counter--;
if(counter == 0)
{
beginning = i;
break;
}
}
}
else if(head[headLen-1].match('[0-9]{1}')) // find the beginning of the number
{
for(i = headLen-2; i >= 0; i--)
{
if(!head[i].match('[0-9]{1}'))
{
beginning = i+1;
break;
}
}
}
else // the string looks like ...abc^{..}.. so the basis is only one character ('c' in this case)
beginning = headLen-1;
var untouchedHead = head.substr(0,beginning);
var firstArg = head.substr(beginning);
// find the end of pow
var secondArg, untouchedTail;
if(tail[0] != '{')
{
secondArg = tail[0];
untouchedTail = tail.substr(1);
}
else
{
counter = 1;
var len = tail.length;
var end = len+1;
for(i = 1; i < len; i++)
{
if(tail[i] == '{')
counter++;
else if(tail[i] == '}')
counter--;
if(counter == 0)
{
end = i;
break;
}
}
secondArg = tail.substr(1,end-1);
if(end < len-1)
untouchedTail = tail.substr(end+1);
else
untouchedTail = '';
}
return untouchedHead
+ 'pow(' + firstArg + ',' + convertLatexPow(secondArg) + ')'
+ convertLatexPow(untouchedTail);
}
alert(convertLatexPow('2^{3^{4^5}}'));
alert(convertLatexPow('\\frac{3}{9}+\\frac{2^{\\sqrt{4^2}}}{6}'));
alert(convertLatexPow('{a + 2 \\cdot (b + c)}^2'));
Input: '2^{3^{4^5}}'
Output: pow(2,pow(3,pow(4,5)))
Input: '\\frac{3}{9}+\\frac{2^{\\sqrt{4^2}}}{6}'
Output: \frac{3}{9}+\frac{pow(2,\sqrt{pow(4,2)})}{6}
Input: '{a + 2 \\cdot (b + c)}^2'
Output: pow({a + 2 \cdot (b + c)},2)
Notice: It do not parse the \sqrt. you have to do this extra.
Feel free to improve it :)
Notice: ^ in LaTeX does not mean power. It just means superscript. So 2^3 becomes 23 (and looks like "2 to the power of 3"), but \sum_{i=1}^n just becomes better formatted. But you can extend the function above to ignore ^ directly after }.
Notice: As Lucas Trzesniewski mentioned in the comment, 2^3^4 is not converted "correct", but it is also not a valid LaTeX expression.
Edit: Improved the function to convert '{a + 2 \\cdot (b + c)}^2' right.
Notice: In LaTeX exists many ways to write a brace (e.g. (, \left(, [, \lbrace,..).
To be sure this function works fine with all this braces you should convert all that braces to { and } first. Or to normal braces (, but then the function has to be edited to look for ( instead of {.
Notice: The complexity of this function is O(n⋅k), where n is the length of the input and k is the number of ^ in the input. An worst case input would be the first test case 2^{3^{4^{...}}}. But in most cases the function will be much faster. Something about O(n).
You can do it iteratively:
var foo = "2^(3^(4^5))";
while (/\([^^]+\^[^^]+\)/.test(foo)) {
foo = foo.replace(/\(([^^]+)\^([^^]+)\)/, "pow($1,$2)");
}
if (/(.+)\^(.+)/.test(foo)) {
foo = "pow(" + RegExp.$1 + "," + RegExp.$2 + ")";
}
# foo == "pow(2,pow(3,pow(4,5)))"

Categories

Resources