Generating binary numbers with length n with same amount of 1's and 0's - bitmask

Question same as in the title.
I've done two approaches. One is straightforward.
Generate all bitmasks from
2^{n-1}
to
2^n
And for every bitmask check if there is same amount 1's and 0's, if yes, work on it.
And that's the problem, because i have to work on those bitmasks not only count them.
I came with second approach which runs on O(2^{n/2}) time, but seems like it's not generating all bitmasks and i don't know why.
Second approach is like that :
generate all bitmasks from 0 to 2^{n/2} and to have valid bitmask( call it B ) i have to do something like this : B#~B
where ~ is negative.
So for example i have n=6, so i'm going to generate bitmasks with length of 3.
For example i have B=101, so ~B will be 010
and final bitmask would be 101010, as we see, we have same amount of 1's and 0's.
Is this method good or am i implementing something bad ? Maybe some another interesting approach exist?
Thanks
Chris

Try a recursive approach:
void printMasks(int n0, int n1, int mask) {
if (!n0 && !n1) {
cerr << mask << endl;
return;
}
mask <<= 1;
if (n0) {
printMasks(n0-1, n1, mask);
}
if (n1) {
printMasks(n0, n1-1, mask | 1);
}
}
Call printMasks passing it the desired number of 0's and 1's. For example, if you need 3 ones and 3 zeros, call it like this:
printMasks(3, 3, 0);

It's possible, given a binary number, to produce the next higher binary number which has the same number of 'ones', using a constant number of operations on words large enough to hold all the bits (assuming that division by a power of two counts as one operation).
Identify the positions of the least significant '1' (hint: what happens if you decrement the number) and the least significant '0' above that (hint: what happens if you add the "least significant 1" to the original number?) You should change that least significant '0' to a '1', and set the proper number of least-significant bits to '1', and set the intervening bits to '0'.

Related

How to use recursion for a sub set problem in C

I am a beginner trying to teach myself C and I had a problem the other day which I thought would be cool to try and solve with a short program. I found it a bit more difficult to solve than I initially thought. Basically the problem goes like this.
I want to be able to enter a single int value between 0..255 (never outside this range) into a function, and inside the function there is an array of 8 values (1, 2, 4, 8, 16, 32, 64, 128), which can be combined by adding together to get reach the single int value. And then return the different combinations possible. i.e.
Target 192
Returns
64, 128
From what I have read this is a sub set problem and can be solved with recursion, but I am really struggling to put the theory and examples I've found into practice. If someone could help me out or even put me in the right direction to try and solve.
Hint: try the "bitwise and" operator (&)
First of all, it's a good idea to keep I/O and algorithms separated. So you generally shouldn't design functions which take user input and performs some algorithm at the same time.
Next up "can be solved with recursion" is not a goal of it's own. Recursion is dangerous, inefficient and hard to read. There exists very few cases where it should be used in C programming and no cases where beginners should use it at all. Most of the time, recursion in C simply boils down to: "I could paint this barn while standing on my hands at the same time"... well maybe you could, maybe you could do it without risk breaking your neck, maybe you can even do it as quickly as if you were standing upright (not likely), but why would you do it?
Program design aside, the algorithm you are looking for is closely related to binary numbers. Any number in any base can be formed by:
digitn * basen + digitn-1 * basen-1... + digit0 * base0.
In case of binary (base 2) numbers manually, for example 111 can be manually decoded to decimal as:
1 * 22 + 1 * 21 + 1 * 20 = 4 + 2 + 1 decimal = 7 decimal.
Now if we compare this with your algorithm, the multipliers above for base 2 correspond to 1, 2, 4, 8...
Conveniently, all numbers in C are actually raw binary. They only get translated to other bases when doing user input/output. So what you need for your algorithm is simply a way to check individual digits of a binary number are set or not.
This can be done with the & "bitwise AND" and << "bitwise left shift" operators. The bitwise left shift to shift the value 1 left to get the various multipliers: 0b=0, 1b=1, 10b=2, 100b=4 and so on. And then bitwise AND to mask out an individual bit from the rest, to see if it is set or not. If it isn't set, well then by the above formula we get 0*basen for that digit, so it will be zero and can be ignored.
Writing the actual C code for that is actually quite easy:
for(int i=0; i<8; i++)
{
unsigned int mask = 1u << i;
if(mask & number)
{
printf("%u\n", mask);
}
}
(This is using unsigned numbers to avoid various common bugs, but that's a topic of its own.)

Bubble sorting max number of times?

I am trying to create a function that sorts 100 random numbers using bubble sort.
I think I might be doing something wrong, however.. Let me show you my code first:
#define MAXVALUE 100
void sortera_nummer(int slumptal[]){
int i,j,temp,k=0;
for(i=0;i<MAXVALUE;i++){
for(j=MAXVALUE-1;j>i;j--){
if(slumptal[j-1]>slumptal[j]){
temp=slumptal[j-1];
slumptal[j-1]=slumptal[j];
slumptal[j]=temp;
k++;
}
}
}
printf("K = %d",k);
}
The numbers all get sorted from lowest to highest, so the sorting works. But I'm getting K = an unexpectedly high number. (It's been everywhere between 2300 to 2700.)
So now I'm wondering - what should be the max number of times a properly working bubble sort could run with 100 elements? What's the equation for calculating it?
(This is my first post here, I'm sorry if I made any mistakes.)
Thanks in advance.
The worst case scenario is if the input array is sorted in descending order. The first loop executes 99 times, the next 98, the next 97...... which equates to "sum(n) from n=99 to n=1" , which means the worst case is n(n+1)/2, in your case n=99 that's 4950.

Inaccurate results with OpenCL Reduction example

I am working with the OpenCL reduction example provided by Apple here
After a few days of dissecting it, I understand the basics; I've converted it to a version that runs more or less reliably on c++ (Openframeworks) and finds the largest number in the input set.
However, in doing so, a few questions have arisen as follows:
why are multiple passes used? the most I have been able to cause the reduction to require is two; the latter pass only taking a very low number of elements and so being very unsuitable for an openCL process (i.e. wouldn't it be better to stick to a single pass and then process the results of that on the cpu?)
when I set the 'count' number of elements to a very high number (24M and up) and the type to a float4, I get inaccurate (or totally wrong) results. Why is this?
in the openCL kernels, can anyone explain what is being done here:
while (i < n){
int a = LOAD_GLOBAL_I1(input, i);
int b = LOAD_GLOBAL_I1(input, i + group_size);
int s = LOAD_LOCAL_I1(shared, local_id);
STORE_LOCAL_I1(shared, local_id, (a + b + s));
i += local_stride;
}
as opposed to what is being done here?
#define ACCUM_LOCAL_I1(s, i, j) \
{ \
int x = ((__local int*)(s))[(size_t)(i)]; \
int y = ((__local int*)(s))[(size_t)(j)]; \
((__local int*)(s))[(size_t)(i)] = (x + y); \
}
Thanks!
S
To answer the first 2 questions:
why are multiple passes used?
Reducing millions of elements to a few thousands can be done in parallel with a device utilization of almost 100%. But the final step is quite tricky. So, instead of keeping everything in one shot and have multiple threads idle, Apple implementation decided to do a first pass reduction; then adapt the work items to the new reduction problem, and finally completing it.
Ii is a very specific optimization for OpenCL, but it may not be for C++.
when I set the 'count' number of elements to a very high number (24M
and up) and the type to a float4, I get inaccurate (or totally wrong)
results. Why is this?
A float32 precision is 2^23 the remainder. Values higher than 24M = 1.43 x 2^24 (in float representation), have an error in the range +/-(2^24/2^23)/2 ~= 1.
That means, if you do:
float A=24000000;
float B= A + 1; //~1 error here
The operator error is in the range of the data, therefore... big errors if you repeat that in a loop!
This will not happen in 64bits CPUs, because the 32bits float math uses internally 48bits precision, therefore avoiding these errors. However if you get the float close to 2^48 they will happen as well. But that is not the typical case for normal "counting" integers.
The problem is with the precision of 32 bit floats. You're not the first person to ask about this either. OpenCL reduction result wrong with large floats

Whats wrong with my division?

I have a 16-bits sample between -32768 and 32767.
To save space I want to convert it to a 8-bits sample, so I divide the sample by 256, and add 128.
-32768 / 256 = -128 + 128 = 0
32767 / 256 = 127.99 + 128 = 255.99
Now, the 0 will fit perfectly in a byte, but the 255.99 has to be rounded down to 255, causing me to loose precision, because when converting back I'll get 32512 instead of 32767.
How can I do this, without loosing the original min/max values? I know I make a very obvious thought error, but I cant figure out where the mistake lies.
And yes, ofcourse I'm fully aware I lost precision by dividing, and will not be able to deduce the original values from the 8-bit samples, but I just wonder why I don't get the original maximum.
The answers for down-sampling have already been provided.
This answer relates to up-sampling using the full range. Here is a C99 snippet demonstrating how you can spread the error across the full range of your values:
#include <stdio.h>
int main(void)
{
for( int i = 0; i < 256; i++ ) {
unsigned short scaledVal = ((unsigned short)i << 8) + (unsigned short)i;
printf( "%8d%8hu\n", i, scaledVal );
}
return 0;
}
It's quite simple. You shift the value left by 8 and then add the original value back. That means every increase by 1 in the [0,255] range corresponds to an increase by 257 in the [0,65535] range.
I would like to point out that this might give worse results than you began with. For example, if you downsampled 65280 (0xff00) you would get 255, but then upsampling that would give 65535 (0xffff), which is a total error of 255. You will have similarly large errors across most of the higher end of your data range.
You might do better to abandon the notion of going back to the [0,65535] range, and instead round your values by half. That is, shift left and add 127. This means the error is uniform instead of skewed. Because you don't actually know what the original value was, the best you can do is estimate it with a value right in the centre.
To summarize, I think this is more mathematically correct:
unsigned short scaledVal = ((unsigned short)i << 8) + 127;
You don't get the original maximum because you can't represent the number 256 as an 8-bit unsigned integer.
if you're trying to compress your 16 bit integer value into a 8 bit integer value range, you take the most significant 8 bits and keep them while throwing out the least significant 8 bits. Normally this is accomplished by shifting the bits. A >> operator is a shift from most to least significant bits which would work if used 8 times or >>8. You can also just mask out the bytes and divide off the 00s doing your rounding before your division, with something like 8BitInt = (16BitInt & 65280)/256; [65280 a.k.a 0xFF00]
Every bit you shift off of a value halves it, like division by 2, and rounds down.
All of the above is complicated some by the fact that you're dealing with a signed integer.
Finally I'm not 100% certain I got everything right here because really, I haven't tried doing this.

Obscure / encrypt an order number as another number: symmetrical, "random" appearance?

Client has an simple increasing order number (1, 2, 3...). He wants end-users to receive an 8- or 9- digit (digits only -- no characters) "random" number. Obviously, this "random" number actually has to be unique and reversible (it's really an encryption of the actualOrderNumber).
My first thought was to just shuffle some bits. When I showed the client a sample sequence, he complained that subsequent obfuscOrderNumbers were increasing until they hit a "shuffle" point (point where the lower-order bits came into play). He wants the obfuscOrderNumbers to be as random-seeming as possible.
My next thought was to deterministically seed a linear congruential pseudo-random-number generator and then take the actualOrderNumber th value. But in that case, I need to worry about collisions -- the client wants an algorithm that is guaranteed not to collide in at least 10^7 cycles.
My third thought was "eh, just encrypt the darn thing," but if I use a stock encryption library, I'd have to post-process it to get the 8-or-9 digits only requirement.
My fourth thought was to interpret the bits of actualOrderNumber as a Gray-coded integer and return that.
My fifth though was: "I am probably overthinking this. I bet someone on StackOverflow can do this in a couple lines of code."
Pick a 8 or 9 digit number at random, say 839712541. Then, take your order number's binary representation (for this example, I'm not using 2's complement), pad it out to the same number of bits (30), reverse it, and xor the flipped order number and the magic number. For example:
1 = 000000000000000000000000000001
Flip = 100000000000000000000000000000
839712541 = 110010000011001111111100011101
XOR = 010010000011001111111100011101 = 302841629
2 = 000000000000000000000000000010
Flip = 010000000000000000000000000000
839712541 = 110010000011001111111100011101
XOR = 100010000011001111111100011101 = 571277085
To get the order numbers back, xor the output number with your magic number, convert to a bit string, and reverse.
Hash function? http://www.partow.net/programming/hashfunctions/index.html
Will the client require the distribution of obfuscated consecutive order numbers to look like anything in particular?
If you do not want to complicate yourself with encryption, use a combination of bit shuffling with a bit of random salting (if you have bits/digits to spare) XOR-superimposed over some fixed constant (or some function of something that would be readily available alongside the obfuscated order ID at any time, such as perhaps the customer_id who placed the order?)
EDIT
It appears that all the client desires is for an outside party to not be able to infer the progress of sales. In this case a shuffling solution (bit-mapping, e.g. original bit 1 maps to obfuscated bit 6, original bit 6 maps to obfuscated bit 3, etc.) should be more than sufficient. Add some random bits if you really want to make it harder to crack, provided that you have the additional bits available (e.g. assuming original order numbers go only up to 6 digits, but you're allowed 8-9 in the obfuscated order number, then you can use 2-3 digits for randomness before performing bit-mapping). Possibly XOR the result for additional intimidation (an inquisitive party might attempt to generate two consecutive obfuscated orders, XOR them against each other to get rid of the XOR constant, and would then have to deduce which of the non-zero bits come from the salt, and which ones came from an increment, and whether he really got two consecutive order numbers or not... He would have to repeat this for a significant number of what he'd hope are consecutive order numbers in order to crack it.)
EDIT2
You can, of course, allocate completely random numbers for the obfuscated order IDs, store the correspondence to persistent storage (e.g. DB) and perform collision detection as well as de-obfuscation against same storage. A bit of overkill if you ask me, but on the plus side it's the best as far as obfuscation goes (and you implement whichever distribution function your soul desires, and you can change the distribution function anytime you like.)
In 9 digit number, the first digit is a random index between 0 and 7 (or 1-8). Put another random digit at that position. The rest is the "real order number:
Orig order: 100
Random index: 5
Random digit: 4 (guaranteed, rolled a
dice :) )
Result: 500040100
Orig Nr: 101
Random index: 2
Random digit 6
Result: 200001061
You can decide that the 5th (or any other) digit is the index.
Or, if you can live with real order numbers of 6 digits, then you can introduce "secondary" index as well. And you can reverse the order of the digits in the "real" order nr.
I saw this rather late, (!) hence my rather belated response. It may be useful to others coming along later.
You said: "My third thought was "eh, just encrypt the darn thing," but if I use a stock encryption library, I'd have to post-process it to get the 8-or-9 digits only requirement."
That is correct. Encryption is reversible and guaranteed to be unique for a given input. As you point out, most standard encryptions do not have the right block size. There is one however, Hasty Pudding Cipher which can have any block size from 1 bit upwards.
Alternatively you can write your own. Given that you don't need something the NSA can't crack, then you can construct a simple Feistel cipher to meet your needs.
If your Order Id is unique, Simply you can make a prefix and add/mix that prefix with your order Id.
Something like this:
long pre = DateTime.Now.Ticks % 100;
string prefix = pre.ToString();
string number = prefix + YOURID.ToString()
<?PHP
$cry = array(0=>5,1=>3,2=>9,3=>2,4=>7,5=>6,6=>1,7=>8,8=>0,9=>4);
function enc($e,$cry,$k){
if(strlen($e)>10)die("max encrypt digits is 10");
if(strlen($e) >= $k)die("Request encrypt must be lesser than its length");
if(strlen($e) ==0)die("must pass some numbers");
$ct = $e;
$jump = ($k-1)-strlen($e);
$ency = $cry[(strlen($e))];
$n = 0;
for($a=0;$a<$k-1;$a++){
if($jump > 0){
if($a%2 == 1){
$ency .=rand(0,9);
$jump -=1;
}else{
if(isset($ct[$n])){
$ency.=$cry[$ct[$n]];
$n++;
}else{
$ency .=rand(0,9);
$jump -=1;
}
}
}else{
$ency.= $cry[$ct[$n]];
$n++;
}
}
return $ency;
}
function dec($e,$cry){
//$decy = substr($e,6);
$ar = str_split($e,1);
$len = array_search($ar[0], $cry);
$jump = strlen($e)-($len+1);
$val = "";
for($i=1;$i<strlen($e);$i++){
if($i%2==0){
if($jump >0){
//$val .=array_search($e[$i], $cry);
$jump--;
}else{
$val .=array_search($e[$i], $cry);
}
}else{
if($len > 0){
$val .=array_search($e[$i], $cry);
$len--;
}else{
$jump--;
}
}
}
return $val;
}
if(isset($_GET["n"])){
$n = $_GET["n"];
}else{
$n = 1000;
}
$str = 1253;
$str = enc($str,$cry,15);
echo "Encerypted Value : ".$str ."<br/>";
$str = dec($str,$cry);
echo "Decrypted Value : ".$str ."<br/>";
?>

Resources