Find all ways to insert zeroes into a bit pattern
Hopefully, this will make it easier to wrap your head around it (please read through this with a pen and paper in hand).
Say the number of zeroes (starting from the right) is x1, x2, ..., xn. eg: if the bit pattern is 00001110001001 then x1 = 0, x2 = 2, x3 = 3, x4 = 4. n is one more than the number of blocks of ones. Observe that knowing x1, x2, ..., xn is enough to figure out the bit-pattern.
Now if the total number of 1's you have is S and total number of bits you have available is M then we must have that
x1 + x2 + ... + xn = M - S
and x1 ≥ 0, xn ≥ 0, x2 ≥ 1, x3 ≥ 1, ...
Let z1 = x1 + 1 and zn = xn + 1
Thus we have
z1 + x2 + ... xn-1 + zn = M - S + 2
Where z1 ≥ 1, x2 ≥ 1, x3 ≥ 1, ..., zn ≥ 1.
Now consider a partition of M-S+2 items where each partition has at least one item. Any partition corresponds to a solution of the above equation and a solution corresponds to a partition in a 1-1 fashion.
Place the M-S+2 items along a line. To get a partition, consider placing n-1 sticks in the M-S+2-1 = M-S+1 spots available, between the items.
Thus a solution (and ultimately your required bit-pattern) uniquely corresponds to a way of choosing n-1 spots among M-S+1 spots.
In case of 5 bits, and 1 bits being 1 and 1.
You have n = 3, M = 5, and S = 2.
Thus you have M-S+1 choose n-1 = 4 choose 2 = 6 possiblities.
Enumerating n choose r combinations is a standard problem and you should find a large variety of solutions (some of them very clever!) for that on the web.
For an example see here: http://compprog.files.wordpress.com/2007/10/comb1.c which seems to support a 'lazy' enumeration: next_combination and does not require huge amounts of memory.
I'm not going to give you Objective-C code mainly because:
- I only know Objective-C on a very superficial level.
- I don't have the desire to write all the memory management code required to get this working in a language like C, and it would only detract from the readability anyway.
Instead I will give you some ideas and some code showing how I would implement this in a higher language with generators and garbage collection (Python in this case) and a hint on how to do it without generators. Hopefully someone else may be able to port the code for you if you cannot do it yourself.
I would think about your problem in a slightly different way:
- How many leading zeros are there in your initial "flushed-right" pattern.
- How many ways are there to partition that number of zeros into n partitions.
In your last example you have two leading zeros and three partitions with separators '10' and '1':
2 0 0: 00101 1 1 0: 01001 1 0 1: 01010 0 2 0: 10001 0 1 1: 10010 0 0 2: 10100
The separators are always of the form 111..10
except the last which is just 111..1
without the trailing zero.
To enumerate the above partitions use a function like the following in Python:
def partitions(n, x):
if n == 1:
yield [x]
else:
for i in range(x + 1):
for p in partitions(n - 1, x - i):
yield [i] + p
for p in partitions(3, 2):
print p
Result:
[0, 0, 2]
[0, 1, 1]
[0, 2, 0]
[1, 0, 1]
[1, 1, 0]
[2, 0, 0]
Once you have these partitions it is simple to construct the patterns.
One challenge is that Objective-C doesn't have built-in support for the yield construct. The following rewrite of the above function may be easier to convert to Objective-C:
def partitions(n, x):
if n == 1:
return [[x]]
else:
result = []
for i in range(x + 1):
for p in partitions(n - 1, x - i):
result.append([i] + p)
return result
I hope that is of some use to you.