Less White
Less White

Reputation: 589

How to use the C++ std to count leading and trailing zeros of a collection of integers

Could we replace a loop by calls to the standard library to count the leading zeros in a collection of integers?

I am learning std but can't figure a way to use something like count or count_if for this situation since I need to know the previous element.

int collection[] = { 0,0,0,0,6,3,1,3,5,0,0 };
auto collectionSize = sizeof(collection) / sizeof(collection[0]);

auto countLeadingZeros = 0;
for (auto idx = 0; idx < collectionSize; idx++)
{
    if (collection[idx] == 0)
        countLeadingZeros++;
    else
        break;
}
// leading zeros: 4*0
cout << "leading zeros: " << countLeadingZeros << "*0" << endl;

I have a similar case to count the trailing zeros in the same collection.

auto countTrailingZeros = 0;
for (auto idx = collectionSize - 1; idx >= 0; idx--)
{
    if (collection[idx] == 0)
        countTrailingZeros++;
    else
        break;
}
// trailing zeros: 2*0
cout << "trailing zeros: " << countTrailingZeros << "*0" << endl;

Below a complete example that builds.

#include <iostream>

using namespace std;

int main()
{
    int collection[] = { 0,0,0,0,6,3,1,3,5,0,0 };
    auto collectionSize = sizeof(collection) / sizeof(collection[0]);

    auto countLeadingZeros = 0;
    for (auto idx = 0; idx < collectionSize; idx++)
    {
        if (collection[idx] == 0)
            countLeadingZeros++;
        else
            break;
    }
    cout << "leading zeros: " << countLeadingZeros << "*0" << endl;

    auto countTrailingZeros = 0;
    for (auto idx = collectionSize - 1; idx >= 0; idx--)
    {
        if (collection[idx] == 0)
            countTrailingZeros++;
        else
            break;
    }
    cout << "trailing zeros: " << countTrailingZeros << "*0" << endl;


    return 0;
}

Upvotes: 1

Views: 1059

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

You can use either the standard algorithm std::find_if or the standard algorithm std::find_if_not.

Here is a demonstrative program that uses the standard algorithm std::find_if_not.

#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>

int main()
{
    int collection[] = { 0, 0, 0, 0, 6, 3, 1, 3, 5, 0, 0 };
    std::size_t n = 0;

    auto first = std::find_if_not(std::begin(collection),
                              std::end(collection), 
                              std::bind2nd(std::equal_to<int>(), 0));

    n += std::distance(std::begin(collection), first);

    auto last = std::find_if_not(std::rbegin(collection),
                         std::reverse_iterator<int *>( first ),
                         std::bind2nd(std::equal_to<int>(), 0));

    n += std::distance(std::rbegin(collection), last );

    std::cout << n << std::endl;

    return 0;
}

The program output is

6

Upvotes: 0

Curious
Curious

Reputation: 21540

You can use std::find_if and reverse iterators

#include <iostream>
#include <algorithm>
#include <vector>

using std::cout;
using std::endl;

int main() {
    auto vec = std::vector<int>{0, 0, 1, 0};
    auto first_non_zero = std::find_if(vec.cbegin(), vec.cend(),
    [](auto integer) {
        return integer != 0;
    });
    auto first_non_zero_end = std::find_if(vec.crbegin(), vec.crend(),
    [](auto integer) {
        return integer != 0;
    });
    auto leading_zeros = std::distance(vec.cbegin(), first_non_zero);
    auto trailing_zeros = std::distance(vec.crbegin(), first_non_zero_end);

    cout << "leading zeros " << leading_zeros << endl;
    cout << "trailing zeros " << trailing_zeros << endl;
}

Upvotes: 2

Jeremy Roman
Jeremy Roman

Reputation: 16355

One way would be to use std::find_if.

auto countLeadingZeros = std::find_if(
    std::begin(collection), std::end(collection),
    [](int x) { return x != 0; }) - std::begin(collection);
auto countTrailingZeros = std::find_if(
    std::rbegin(collection), std::rend(collection),
    [](int x) { return x != 0; }) - std::rbegin(collection);

Upvotes: 6

Related Questions