Solved.

I'm working on creating this, however, my program gives me a weird integer binary value when counting the occurrences. For example, when a decimal is entered, it outputs a bunch of random numbers instead of counting the occurrence.

Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52


#include <iostream>
#include <string>
using namespace std;

unsigned count_bit_matches( unsigned long value, unsigned long pattern )
{
  unsigned result = 0;
  unsigned long mask = 1;
  
  for (unsigned long p = pattern; p; p >>= 1)
    mask <<= 1;
  mask != 1;
  
  while (value)
  {
    result += ((value & mask) == pattern);
    value >>= 1;
  }
  
  return result;
}

string to_binary( unsigned long n )
{
  string result;
  while (n)
  {
    result = (char)((n & 1) + '0') + result;
    n >>= 1;
  }
  return result.empty() ? string("0") : result;
}

void test( unsigned value, unsigned pattern )
{
  cout << value << ": '" << to_binary( value ) 
       << "', "          << count_bit_matches( value, pattern ) 
       << " groups of '" << to_binary( pattern ) << "'.\n";
}

int main()
{
  test( 183, 3 );
  test( 183, 7 );
  test( 183, 5 );
  test( 183, 2 );
  test( 183, 4 );
  return 0;
}


Thanks.


EDIT: Nevermind, simple mistake, mask != 1 should have been mask -= 1.
Last edited on
You could do it with bit-shifting and masking:
1
2
3
4
5
6
7
unsigned int count1s(unsigned int x)
{
  unsigned int output = 0;
  for (int i = 0; i < sizeof(unsigned int)*8; ++i)
    output += ( (x >> i) & 0x1 )
  return output;
}
Solved.
Last edited on
You could use a std::bitset[1] and call the member function std::bitset::count to count the number of set bits.

[1]http://www.cplusplus.com/reference/bitset/bitset/?kw=bitset
[2]http://www.cplusplus.com/reference/bitset/bitset/count/
You can play around with this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <string>
#include <limits>
#include <type_traits>


template <typename int_type,
          class = typename std::enable_if<std::is_unsigned<int_type>::value>::type>
std::string to_binary(int_type num)
{
    if (num == 0)
        return std::string(1, '0');

    // begin with most significant bit:
    int_type mask = 1 << (std::numeric_limits<int_type>::digits - 1);

    while (mask && !(mask&num)) // skip over leading 0s
        mask >>= 1;

    std::string result;
    while (mask)
    {
        result += (mask & num) ? '1' : '0';
        mask >>= 1;
    }

    return result;
}

template <typename int_type,
          class = typename std::enable_if<std::is_unsigned<int_type>::value>::type>
unsigned groups_of_1s(int_type num)
{
    int_type mask = 1;
    bool in_group = false;
    unsigned count = 0;

    while (mask)
    {
        if (mask & num)
        {
            if (!in_group)
            {
                in_group = true;
                ++count;
            }
        }
        else
            in_group = false;

        mask <<= 1;
    }

    return count;
}

int main()
{
    const unsigned value = 183;
    std::cout << value << ": " << to_binary(value) << ", ";
    std::cout << groups_of_1s(value) << " groups of 1.\n";
}


http://ideone.com/GL8mH6
Solved.
Last edited on
I don't think your compiler supports that feature of C++11, I know that GCC 4.8.1 does so you could use that instead.

At any rate, here is the doe example @cire gave: http://ideone.com/XeETl9
No one really read the question. OP is looking for '11's, not '1's.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
using namespace std;

unsigned count_bit_matches( unsigned long value, unsigned long pattern )
{
  unsigned result = 0;
  unsigned long mask = 1;
  
  for (unsigned long p = pattern; p; p >>= 1)
    mask <<= 1;
  mask -= 1;
  
  while (value)
  {
    result += ((value & mask) == pattern);
    value >>= 1;
  }
  
  return result;
}

string to_binary( unsigned long n )
{
  string result;
  while (n)
  {
    result = (char)((n & 1) + '0') + result;
    n >>= 1;
  }
  return result.empty() ? string("0") : result;
}

void test( unsigned value, unsigned pattern )
{
  cout << value << ": '" << to_binary( value ) 
       << "', "          << count_bit_matches( value, pattern ) 
       << " groups of '" << to_binary( pattern ) << "'.\n";
}

int main()
{
  test( 183, 3 );
  test( 183, 7 );
  test( 183, 5 );
  test( 183, 2 );
  test( 183, 4 );
  return 0;
}

Hope this helps.
I wanted to test out your code, however, when I try to compile it, it gives me an error saying:

error C4519: default template arguments are only allowed on a class template.


You can change the lines that look like:
1
2
template <typename int_type,
          class = typename std::enable_if<std::is_unsigned<int_type>::value>::type>


to:
template <typename int_type>

to get around that.
Topic archived. No new replies allowed.