I am trying to write a function which takes an array of integers, and outputs a hash value to signify their arrangement order. The hash key should be as small as possible (we're dealing with embedded and space/execution optimization is critical)
template<size_t N>
int CalculateHashOfSortOrder(int* itemsBegin)
{
// return ???
}
In other words, an array [ 4, 2, 1, 3 ]
should produce an ID which reflects their order and would match any of the following arrays:
[ 4, 2, 1, 3 ]
[ 4, 2, 0, 3 ]
[ 400, 200, 100, 300]
et al
I am at a loss for how to do this in the most efficient way possible. What is the algorithm to approach this? The methods I come up with seem extremely slow.
For example, given the above example, there are 24 possibly arrangements (4 * 3 * 2 * 1), which would fit into 5 bits. Those bits can be calculated like this:
- 1st value (1). There are 4 positions possible, so 2 bits are needed to describe its position. This value is at position 2 (0-based). So push binary
10
. - 2nd value (2). There are 3 positions possible, so 2 bits are needed. It's at position 1, so push binary
01
. Hash key is now1001b
. - 3rd value (3). There are 2 positions possible, so 1 bit is needed. It's at position 1 of the remaining values, so push
1
.
The resulting key is 10011b
, but I don't see a clear way to make that anything but obnoxiously inefficient. I think there's another way to approach this problem I just haven't thought of.
edit: A couple ideas come to mind:
- Calculate the rank of each item in the array, and hash the rank array. Then by what method can you pack that rank array into a theoretically-smallest ID? This appears to be the most vexing element of my question.
- Find a way to save item rank as they're inserted, optimizing #1
- For sufficiently small # of items (<10), it may be possible to just generate a huge tree of
if()
statements via metaprogramming. Need to see if exe size would be a problem.