ledow
Member
Okay, I have a need for a function which does the following:
CODE
int next_binary_string_with_x_bits(int start, int x)
It takes a number (start) which has "x" 1's in it's binary expression. It then returns the next highest number which has the same property.
So:
CODE
next_binary_string_with_x_bits(0, 2) gives 3 <-- 0011 in binary, the first number after zero to have two bits set.
next_binary_string_with_x_bits(3, 2) gives 5 <-- 0101 in binary, the next number after 3 to have two bits set.
next_binary_string_with_x_bits(5, 2) gives 6 <-- 0110 in binary
next_binary_string_with_x_bits(6, 2) gives 9 <-- 1001 in binary
and
CODE
next_binary_string_with_x_bits(0, 5) gives 31 <-- 11111 in binary, the first number after 0 to have 5 bits set.
next_binary_string_with_x_bits(31, 5) gives 47 <-- 101111 in binary
Now, I've tried a few things that work but I can't seem to find a nice, fast way of doing this quickly. Even my primitive mind's recall of the maths that I've done hasn't produced anything better than the function below which would give significant speedups.
I need to be able to run this function a LOT - it's used several dozen times in an O(N) algorithm to generate a puzzle of certain sizes, but I also need to build very deep game trees of this puzzle using the same method and that means it needs to be FAST if it's to run on the GP2X. I need it to run on numbers which are mostly within the integer range (e.g. no more than 65535, usually not even more than 256). At the moment, I have something similar to:
CODE
int next_binary_string_with_x_bits(int start, int x)
{
// Start at "start", keep adding one.
for(int i=start;i<MAX_INT;i++)
// If the number of the bits is right, break early and return the number.
if(count_bits(i) == count_bits(x))
return(i)
return(-1) // Error condition for "there isn't a suitable binary string".
}
where count_bits is a very fast function for counting the number of 1's in a binary representation.
That's not exact code, just a hint of the way I'm doing it... the exact code is a lot nicer, caches certain parts, prevents overflow, limits the size of the output integer to a requested limit (e.g. 8 bits), terminates much quicker without having to iterate all the way up to MAX_INT and has other little optimisations here and there.
Count_bits functions are ten-a-penny and there's all sorts of optimisation on them that makes them incredibly fast in both plain C and machine code, which is why I'm able to use them in such a way and get results which allow me to continue coding the more interesting parts of this particular puzzle. However, this function can still take quite a while to return on 200MHz - 600MHz machines. Whereas you can get count_bits functions which return in a time proportional to the number of bits actually set, this function returns in the time it takes to count up to the next number that has x bits set (which varies enormously and can be a long time.... take, for example, the number 134217728. This has binary expression: 1000000000000000000000000000. Now say that you ask for the next number with only 1 bit set....).
I imagine that there HAS to be a quicker way of coding this function, even if it means horrible things like precomputed tables, fancy XOR'ing or something. It seems an obvious candidate for some sort of boolean operations that provide the answer extremely quickly using low-level routines, but does anyone have any idea on how to implement a nice, fast, programmatic way of generating the results needed. I can do the speedups like caching answers and so on but I still need a fast way of generating the actual data on startup with a nice fast function like the one above.
Any language will do - I can translate most things to the language of my choice. I need it to do at least integers, but the possibility of expansion is vital because these puzzles can get very silly very quickly (One example would be a 64x64 puzzle, which would require this function to operate on binary strings 127bits long with an average of 64 bits set... so you're looking at some incredibly large numbers (2^127) and HUGE gaps between answers).
Anyone fancy a bit of mind-blowing?
CODE
int next_binary_string_with_x_bits(int start, int x)
It takes a number (start) which has "x" 1's in it's binary expression. It then returns the next highest number which has the same property.
So:
CODE
next_binary_string_with_x_bits(0, 2) gives 3 <-- 0011 in binary, the first number after zero to have two bits set.
next_binary_string_with_x_bits(3, 2) gives 5 <-- 0101 in binary, the next number after 3 to have two bits set.
next_binary_string_with_x_bits(5, 2) gives 6 <-- 0110 in binary
next_binary_string_with_x_bits(6, 2) gives 9 <-- 1001 in binary
and
CODE
next_binary_string_with_x_bits(0, 5) gives 31 <-- 11111 in binary, the first number after 0 to have 5 bits set.
next_binary_string_with_x_bits(31, 5) gives 47 <-- 101111 in binary
Now, I've tried a few things that work but I can't seem to find a nice, fast way of doing this quickly. Even my primitive mind's recall of the maths that I've done hasn't produced anything better than the function below which would give significant speedups.
I need to be able to run this function a LOT - it's used several dozen times in an O(N) algorithm to generate a puzzle of certain sizes, but I also need to build very deep game trees of this puzzle using the same method and that means it needs to be FAST if it's to run on the GP2X. I need it to run on numbers which are mostly within the integer range (e.g. no more than 65535, usually not even more than 256). At the moment, I have something similar to:
CODE
int next_binary_string_with_x_bits(int start, int x)
{
// Start at "start", keep adding one.
for(int i=start;i<MAX_INT;i++)
// If the number of the bits is right, break early and return the number.
if(count_bits(i) == count_bits(x))
return(i)
return(-1) // Error condition for "there isn't a suitable binary string".
}
where count_bits is a very fast function for counting the number of 1's in a binary representation.
That's not exact code, just a hint of the way I'm doing it... the exact code is a lot nicer, caches certain parts, prevents overflow, limits the size of the output integer to a requested limit (e.g. 8 bits), terminates much quicker without having to iterate all the way up to MAX_INT and has other little optimisations here and there.
Count_bits functions are ten-a-penny and there's all sorts of optimisation on them that makes them incredibly fast in both plain C and machine code, which is why I'm able to use them in such a way and get results which allow me to continue coding the more interesting parts of this particular puzzle. However, this function can still take quite a while to return on 200MHz - 600MHz machines. Whereas you can get count_bits functions which return in a time proportional to the number of bits actually set, this function returns in the time it takes to count up to the next number that has x bits set (which varies enormously and can be a long time.... take, for example, the number 134217728. This has binary expression: 1000000000000000000000000000. Now say that you ask for the next number with only 1 bit set....).
I imagine that there HAS to be a quicker way of coding this function, even if it means horrible things like precomputed tables, fancy XOR'ing or something. It seems an obvious candidate for some sort of boolean operations that provide the answer extremely quickly using low-level routines, but does anyone have any idea on how to implement a nice, fast, programmatic way of generating the results needed. I can do the speedups like caching answers and so on but I still need a fast way of generating the actual data on startup with a nice fast function like the one above.
Any language will do - I can translate most things to the language of my choice. I need it to do at least integers, but the possibility of expansion is vital because these puzzles can get very silly very quickly (One example would be a 64x64 puzzle, which would require this function to operate on binary strings 127bits long with an average of 64 bits set... so you're looking at some incredibly large numbers (2^127) and HUGE gaps between answers).
Anyone fancy a bit of mind-blowing?