0

I am trying to find an efficient way to get the majority of corresponding bit in a group of same sized integers. For example in the given integers:

12 => 1 1 0 0
9  => 1 0 0 1
9  => 1 0 0 1
3  => 0 0 1 1

the majority of bit (column wise) can be represented as:

      1 0 0 1 

If there are equal number of 1's and 0's (column wise), it should be 1. I would like to achieve this using integers without converting the integer to binary string if possible.

Atee
  • 11
  • 3

1 Answers1

1

In C, this could be something like this:

unsigned arr[] = { 12, 9, 9, 3 };     //  values to loop through
unsigned len = sizeof(arr) / sizeof(arr[0]);   //  # of values
unsigned result = 0;                  //  collect result here
unsigned bits = sizeof(arr[0]) * 8;   //  number of bits to consider
unsigned threshold = len / 2 + ((len & 1) ? 1 : 0);  //  minimum # of 1 to get a 1
unsigned bit = 1 << (bits - 1);       //  bit mask; point to most significant bit position

for (unsigned pos = 0; pos < bits; pos++) {
    unsigned ones = 0;
    for (unsigned i = 0; i < len; i++) {
        if ((bit & arr[i]) != 0) {
            ones++;
        }
    }

    result = (result << 1) + ((ones >= threshold) ? 1 : 0);
    bit = bit >> 1;
}

printf("\n%d\n", result);

The outer loop shifts a bitmask from the most-significant to the least-significant end. The inner loop counts the bits set to 1. If the 1 bits exceed a threshold, a 1 is shifted into the result. Otherwise, a 0 is shifted in. At the end, the result holds the majority bits as requested.

This could be further optimized but was not to keep readability up.


Simplified for special case len==4

unsigned arr[] = { 12, 9, 9, 3 };     //  values to loop through
unsigned len = sizeof(arr) / sizeof(arr[0]);   //  # of values
unsigned result = 0;                  //  collect result here

//  for len==4, majority means that 2 or more bits are 1
for (unsigned i = 0; i < len - 1; i++)
    for (unsigned j = i + 1; j < len; j++) {
        result = result | (arr[i] & arr[j]);
    }

printf("\n%d\n", result);
Axel Kemper
  • 10,544
  • 2
  • 31
  • 54