2

I'm looking for a function that maps two (positive) integers into a single new integer, which can be reversed to the original combination. The question has been asked before, for example Mapping two integers to one, in a unique and deterministic way. The difference is that one of the integers is bound to an upper bound which is quite small, for example 50. The other integer is unbound.

What i'm trying to solve is that I have and 1-50 arrays with numbers 1 - max int (but mostly < 10.000.000).

array1 {1,2,3,4,5,6,7..N)  
array2 {1,2,3,4,5,6,7..N)  
array50 {1,2,3,4,5,6,7..N)  

Now I want to create a single new array which combines these N arrays to a single new array, where each number is reversable to the original array. So I thought about creating pairs, one number pointing to the array and one to the actual number in the array.

If I use the default functions like Cantor Pairing Function I get huge numbers very fast, and i'm trying to keep those numbers as small as possible. It would be preferably if the biggest part would just fit in a Int32 instead of a long. I think it should be possible because one of the numbers in my pair is bounded by 50, but I can't figure out how.

Joeri
  • 205
  • 1
  • 8
  • 1
    It can clearly only be done if both are bounded, because `int` is bounded – harold Oct 13 '17 at 14:33
  • *"I get huge numbers very fast"* - bigger than [`BigInteger`](https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx) ? – Sinatr Oct 13 '17 at 14:35
  • For example if one part goes from 1 - max int, then only 1 extra bit can be stuffed in.. – harold Oct 13 '17 at 14:36
  • Yes, both are bounded. But one is bounded between 1-50 the other between 1-MaxInt. @Sinatr: If you use Cantor Pairing with for example 100000,4 you get 5000450014. Which works, but at 200000 you are already overflowing the int32 (20000900014) – Joeri Oct 13 '17 at 14:47
  • Thing is 1..MaxInt requires 31 bits and 1..50 requires 6 bits, and (31+6)>32, so it's just not possible to store both numbers simultaneously in 32 bits. – Matthew Watson Oct 13 '17 at 14:49
  • @MatthewWatson You're correct. So, what if we bounded this number also, so it would actually fit in the Int32 – Joeri Oct 13 '17 at 14:52
  • If you need 6 bits for the 1..50 you would be limited to 32-6 = 26 bits for the larger number, which would restrict it to 0..67,108,863 – Matthew Watson Oct 13 '17 at 14:57
  • Trying to invent absolute compression... like [perpetuum mobile](https://en.wikipedia.org/wiki/Perpetuum_mobile) it is somewhat hard :) to achieve... Do you really expect to succeed in getting some amount of random bits and reversibly compress them to 1/N size for N>1? Some basics - https://en.wikipedia.org/wiki/Data_compression before you go too far. – Alexei Levenkov Oct 13 '17 at 15:04

1 Answers1

0

If you have two numbers

  • a from 0 to a_max - 1
  • b from 0 to 232/a_max - 1

you can combine them as

x = a + a_max*b;

and the combined number x will fit into a 32 bit unsigned integer.

To decode them, use

a = x%a_max;
b = x/a_max;

It is not possible to find a more efficient packing, because every possible output value is used. (There are no 'gaps' in the output.) If the bounds for b are too narrow, a larger output type must be used.

alain
  • 11,488
  • 2
  • 28
  • 47
  • But the OP has `a_max` = 2^31 which would mean `b` could range from 0 to 1 - but he wants `b` to range from 1..50 – Matthew Watson Oct 13 '17 at 14:54
  • Yes, `b` has to be bounded too, else it is impossible without a larger type. [But it seems a bound may be acceptable for the OP](https://stackoverflow.com/questions/46732213/mapping-two-integers-to-one-with-an-upperbound/#comment80411661_46732213) – alain Oct 13 '17 at 14:57
  • Thanks. It seems so simple, but it does exactly what I was looking for. – Joeri Oct 13 '17 at 15:08