Блог пользователя Kerekiw

Автор Kerekiw, 3 года назад, По-английски

Formulas are given in C/C++, which uses two's complemet

Beginner level

x = (1 << y) ^ x — toggle a bit.

x = (1 << y) | x — addding a bit.

x = ~(1 << y) & x — removing a bit.

if (1 << y & x) — check whether y-th bit is set.

Intermediate level

-x = ~x + 1 — negative $$$ x $$$ in two's complement representation.

x & (-x) — least significant bit, LSB

if (x && !((x-1) & x) — check whether x is a power of two

Complex level

Bit swap

p = ((x >> a) ^ (x >> b)) & 1
x ^= (p << a)
x ^= (p << b)

Number of set bits

aka population count. x = x & (x-1) removes least significant bit, Brian Kernighan method.

for (c = 0; x; c++)
    x = x & (x-1)

Swapping values

b ^= a ^= b;
a ^= b;

All submasks of mask

Excluding blank mask. Also, enumerating all masks and their submasks is $$$ O(3^n) $$$.

for (int s = m; s; s = (s-1)&m)
	//do something

Bit scan forward

BSF, null indexed position of LSB. $$$ x $$$ should not be zero.

x = x & (-x);
int pos = 0;
if (x & 0xffff0000) pos += 16;
if (x & 0xff00ff00) pos += 8;
if (x & 0xf0f0f0f0) pos += 4;
if (x & 0xcccccccc) pos += 2;
if (x & 0xaaaaaaaa) pos += 1;

Next permutation

Rearranges bit set of number into the lexicographically next greater permutation.

t = x | (x - 1);
x = (t + 1) | (((~t & -~t) - 1) >> (BSF(v) + 1));

Summary

Most of these are useless or can be replaced with builtin functions, but if some of you find them intersting you should check out this list or this video.

  • Проголосовать: нравится
  • +35
  • Проголосовать: не нравится

»
3 года назад, # |
  Проголосовать: нравится +14 Проголосовать: не нравится

Excluding blank mask, $$$O(3^n)$$$.

It's clearly $$$O(2^n)$$$. $$$O(3^n)$$$ is for enumerating all masks and their submasks.

»
3 года назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится

What does "next permutation" mean?

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Permutes bit set of $$$ x $$$ to lexicographicaly next permutation, assuming they are sorted in ascending order, e.g. $$$ 100101 $$$ will be permuted to $$$ 100110 $$$, $$$ 100110 $$$ will be permuted to $$$ 101001$$$.

»
3 года назад, # |
  Проголосовать: нравится +11 Проголосовать: не нравится
(x&(x-1)) ---> Checking The Power of Two.   :)
»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Iterating over all bits set to 1:

for (int m = mask; m; m &= m - 1) {
    do_something(__builtin_ctz(m));
}

If mask is long long, you need to replace int by long long (obviously) and __builtin_ctz by __builtin_ctzll. Probably C++20 has a method like ctz or something for this

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится +11 Проголосовать: не нравится

    Also its dual (for supermask enumeration), just for the sake of completeness. Here $$$n$$$ is the number of bits.

    for (int m = mask; m < (1 << n); m = (m + 1) | mask) {
        // m is a supermask of m
    }
    
    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      what is a supermask?

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится +13 Проголосовать: не нравится

      My code does not do submask enumeration, it does another thing

      • »
        »
        »
        »
        3 года назад, # ^ |
          Проголосовать: нравится +16 Проголосовать: не нравится

        Ah yes, I somewhat misread the update condition (for submask enumeration it's m = (m - 1) & mask).

        On another note, you can iterate over the zeros in the mask by using the following (very similar) loop (though it is equivalent to doing the same thing as you mentioned with ~mask instead):

        for (int m = mask; m < (1 << n) - 1; m |= (m + 1)) {
            // do something with __builtin_ctz(m + 1)
        }
        

        Note that this gives the locations of the zeros before the position $$$n$$$ (zero-indexed from the right), and needs mask to be less than $$$2^n$$$.

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Zwerr