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
|
#include <iostream>
#include <vector>
#include <type_traits>
#include <cassert>
// returns a pair { iterator to the smallest positive element, iterator to the greatest positive element }
// if the range has no positive elements returns { end, end }.
// if many elements are equal to min or max, the iterator to the first such element is returned.
template < typename ITERATOR >
std::pair<ITERATOR,ITERATOR> min_max_positive_element( ITERATOR begin, ITERATOR end )
{
using value_type = typename std::iterator_traits<ITERATOR>::value_type ;
static_assert( std::is_arithmetic<value_type>::value, "a sequence of numeric values is expected" ) ;
static constexpr auto ZERO = value_type{} ;
// if the value at iter is non-positive, increment iter to 'point' to the next positive value
static const auto positive_element = [] ( ITERATOR iter, ITERATOR iend )
{
while( iter != iend && *iter <= ZERO ) ++iter ;
return iter ;
};
begin = positive_element(begin,end) ;
auto min = begin ;
auto max = begin ;
while( begin != end )
{
if( *begin < *min ) min = begin ;
if( *begin > *max ) max = begin ;
++begin ;
begin = positive_element(begin,end) ;
}
return { min, max } ;
}
int main()
{
{
const std::vector<int> seq { 0, -5, 33, 0, 22, 4, -6, 11, 33, -2, 4, 33, -3, 0 } ;
const auto [min,max] = min_max_positive_element( std::begin(seq), std::end(seq) ) ;
assert( min != std::end(seq) && *min == 4 && *max == 33 ) ;
// if many elements are equal to min or max, the iterator to the first such element is returned.
assert( min == std::begin(seq)+5 && max == std::begin(seq)+2 ) ;
}
{
// no positive elements
const std::vector<double> seq { -1.2, 0.0, -3.4, 0.0, -2.3 } ;
const auto [min,max] = min_max_positive_element( std::begin(seq), std::end(seq) ) ;
//
assert( min == std::end(seq) && max == std::end(seq) ) ;
}
std::cout << "ok\n" ;
}
| |