Reputation: 589
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
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
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
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