0

I need the following function and it needs to be performant. I really don't know how to go about this.

function(value: string): number { ... }

The returned number needs to be between 0 and 15 and always return the same number for given strings. Duplicates are obviously allowed!

I did something similar on Node a while back but I think this would not be performant enough for my use case:

function(value: string): number {
  const hash = crypto.createHash("sha256");
  const hexValue: string = hash.update(value).digest("hex");
  const shortenedHexValue = hexValue.substring(0, 2);
  const decimalValue = parseInt(shortenedHexValue, 16);
  return decimalValue / 2.55;
}

This function returned values > 0 to ~100 for given strings.

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
t-MURO
  • 642
  • 5
  • 10
  • How is this supposed to work if the number is between 0 and 15? You can only have 16 different strings before there are collisions. – kelsny Nov 02 '22 at 13:51
  • 2
    You can do `return value.length % 16;`. It will always return the same number for same string, and the number will be between 0 to 15, included. Of course different string can return the same number, but you can't do anything for that because there are only 16 different possible return values.More simplier : `return 0;`. – AoooR Nov 02 '22 at 13:57
  • @caTS collisions are not an issue! – t-MURO Nov 02 '22 at 14:00
  • 1
    What performance do you aim to achieve ? A simple thing would be to take the first char, and use modulo 16 on its ascii value : `value.charCodeAt(0) % 16` (if the string is not empty, else return 0) – Alois Christen Nov 02 '22 at 14:03
  • @AoooR The input I'm going to give to the function is an ID. So they are all the same length. The number that comes out should always be the same for each ID, but somewhat randomised. If two IDs return the same number, that's not an issue. – t-MURO Nov 02 '22 at 14:08
  • @AloisChristen In my previous reply partially explained why that wont work. The IDs I'm putting in the function are not so random and follow a pattern, so that this approach would not be "random" enough – t-MURO Nov 02 '22 at 14:10
  • @t-MURO ok, I thought that the node version wasn't fast enough. I still don't get "this function returned values > 0 to ~100 for given strings". Could you explain that ? – Alois Christen Nov 02 '22 at 14:14
  • @AoooR actually your reply helped me out to get a solution. Turns out the value im inputting is actually a number and not a string... so a simple % 16 is enough. Seems like a very simple solution but I think I would have not come up with it in such short time! – t-MURO Nov 02 '22 at 18:05

1 Answers1

0

According to the comments under your post, you need something that looks "random", so you can't do:

function hash15(value: string): number {
    return 0;
}

event if it corresponds to all you specifications.

For the random part, we can use ASCII code of each char of your string, as @Alois Christen suggested:

function hash15(value: string): number {
    let res = 0;
    for (let i = 0; i < value.length; i++) {
        res += value.charCodeAt(i);
    }
    return res % 16;
}

If you need it to be faster, you can skip characters:

function hash15(value: string): number {
    let res = 0;
    for (let i = 0; i < value.length / 2; i+=2) {
        res += value.charCodeAt(i);
    }
    return res % 16;
}
AoooR
  • 370
  • 1
  • 9
  • Thanks. I'll mark your reply as solved, though I managed to get a number to do the calculation so the only thing I had to do is % 16 :D – t-MURO Nov 02 '22 at 18:07