Writing a function in javascript that is the inverse of another

1.1k views Asked by At

I'm trying to write a function that is the inverse of the function below.

So that I can get the output from the function foo and generate it's input parameter.

I'm not entirely sure if it's possible.

function foo(str){
    var hexMap = {
        "0":0,
        "1":1,
        "2":2,
        "3":3,
        "4":4,
        "5":5,
        "6":6,
        "7":7,
        "8":8,
        "9":9,
        "A":10,
        "B":11,
        "C":12,
        "D":13,
        "E":14,
        "F":15
    };
    var charList = [];

    str = str.toUpperCase();               


    for (var i = 0; i < str.length; i += 2) {
        charList.push(hexMap[str.charAt(i)] * 16 + hexMap[str.charAt(i + 1)]);
    }

    charList.splice(0, 8);
    charList.splice(0, 123);

    var sliceEnd = charList[0] + charList[1] * 256;
    charList.splice(0, 4);

    charList = charList.slice(0, sliceEnd); 
    return charList;
}
2

There are 2 answers

1
Paul On BEST ANSWER

Your function takes in a string that is hopefully a hexadecimal string using only the characters [0-9a-fA-F]. Then it makes an array where every two hex characters are converted to a decimal integer between 0 and 255. Then the function immediately throws away the first 131 elements from this array. This means that the first 262 characters on your string have no impact on the output of the function (The first 262 characters can be any characters).

Then there is this line:

var sliceEnd = charList[0] + charList[1] * 256;

sliceEnd becomes a number between 0 and 65535 (the maximum size of the resulting array). Based on the characters at indices 262 - 265 in the input string. (Two two digit hex values converted to two integers. The value at position 264 is multiplied by 256 and added to the value at position 262).

Then the resulting array contains the integers converted using the same method from the characters from position 270 to 270 + sliceEnd*2.

MSN is correct that this function is not 1 to 1 and therefore not mathematically invertible, but you can write a function which given an array of less than 65536 integers between 0 and 255 can generate an input string for foo which will give back that array. Specifically the following function will do just that:

function bar(arr){
    var sliceEnd = arr.length;
    var temp = '00' + (sliceEnd & 255).toString(16);
    var first = temp.substring(temp.length - 2);
    temp = '00' + Math.floor(sliceEnd/256).toString(16);
    var second = temp.substring(temp.length - 2);
    var str = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + first + second + '0000';
    for(var i = 0; i < arr.length; i++){
        temp = '00' + arr[i].toString(16);
        str += temp.substring(temp.length - 2);
    }
    return str;
}

This gives you the property that foo(bar(x)) === x (if x is an array of less than 65536 integers between 0 and 255 as stated previously), but not the property bar(foo(x)) === x because as MSN pointed out that property is impossible to achieve for your function.

EG. bar([17,125,12,11]) gives the string:

"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000117dcb" which if you give as input to your function foo you get back the original array: [17,125,12,11], but there are many other inputs (at least 268 of those 0's can be any other of the values in [0-9a-fA-F], and the 04 can be anything greater than 04 which means 22^268*(255 - 4) different strings multiplied by a bit more since that only takes into account either lower case or capitals but not both when multiplying by 255 - 4. regardless 22^268 is a ridiculous number of inputs for one output anyways, and that's ignoring the fact that their are an infinite amount of strings which begin with the string above and have any other hexadecimal string appended to them which will give the same output from foo because of the sliceEnd variable.

2
MSN On

That function is not a 1 to 1 function, i.e., many inputs will generate the same output.