My particular instance of B was small enough to be brute force, with a few tricks to crop the search.
With functions already defined
snoob , returns the next highest number with the same number of bits set (as defined in Hacker Delight, Figure 2-1 (or originally, HAKMEM clause 175))popcount , returns a 1-bit number in its argumentclz , returns the number of consecutive zeros at the most significant end of its argument
The pseudocode for my solution is as follows:
min_ones = max popcount(b) for b in B max_ones = popcount(~0) for i = 0 .. |B|-1: while !(B[i] & 1): B[i] >>= 1 found_ones = false for ones = min_ones .. max_ones: if found_ones: break for S = (1 << ones)-1; clz(S) > 0; S = snoob(S): if !(S & 1): continue for b in B: found = false for N = 0 .. clz(b) - clz(S): if (S >> N) & b == b: found = true break if !found: break if found: print(S) found_ones = true
The first cycle shifts to the right each b, so its least significant bit is 1; this allows us to use only right shifts for N later.
The loop over S begins with the smallest number with the ones bits set; the loop stop condition is not entirely correct, but it works well enough for my purposes.
The cycle over N begins with the alignment of LSB S and b, and then proceeds to the most significant single-digit values โโof S and b.
I am currently leaving the question as unsolved to see if the correct solution appears without brute force or until someone says the problem is NP-hard.
source share