EDIT: bugfix - (O3N) time with zero check:
#include <numeric>
#include <array>
#include <vector>
#include <iostream>
namespace notstd {
template<class T>
auto to_vector(std::initializer_list<T> il) {
return std::vector<T>(il);
}
}
static constexpr struct {
template<class Iter>
void operator()(Iter first, Iter last) const {
if (first != last) {
auto zeros = std::count(first, last, 0);
switch (zeros) {
case 0: {
auto accum = std::accumulate(std::next(first), last,
*first, std::multiplies<>());
std::transform(first, last,
first,
[accum](auto &&v) {
return accum / v;
});
}
break;
case 1: {
auto maybe_multiply = [](auto &&x, auto &&y) { return y == 0 ? x : x * y; };
auto accum = std::accumulate(first, last,
1, maybe_multiply);
std::transform(first, last,
first,
[accum](auto &&v) {
if (v == 0)
return accum;
else
return 0;
});
}
break;
default: {
std::fill(first, last, 0);
} break;
}
}
}
} other_products {};
template<class Container, class Algo>
auto mutate_copy(Container c, Algo algo) {
algo(std::begin(c), std::end(c));
return c;
};
template<class T, class Algo>
auto mutate_copy(std::initializer_list<T> il, Algo &&algo) {
return mutate_copy(notstd::to_vector(il),
std::forward<Algo>(algo));
};
template<class T, std::size_t N, class Algo>
auto mutate_copy(std::array<T, N> const &a, Algo &&algo) {
return mutate_copy(std::vector<T>(a.begin(), a.end()),
std::forward<Algo>(algo));
};
template<class Container, class Algo>
auto &mutate_inplace(Container &c, Algo algo) {
algo(std::begin(c), std::end(c));
return c;
};
template<class Container>
std::ostream &emit(std::ostream &os, Container &&c) {
auto impl = [&os](auto first, auto last) {
using value_type = typename std::iterator_traits<decltype(first)>::value_type;
std::copy(first, last,
std::ostream_iterator<value_type>(os, ", "));
};
impl(std::begin(c), std::end(c));
return os;
}
int main() {
emit(std::cout, mutate_copy({1, 2, 0, 4, 5}, other_products)) << std::endl;
emit(std::cout, mutate_copy({2, 3, 4, 5, 6}, other_products)) << std::endl;
emit(std::cout, mutate_copy({6, 5, 4, 3, 2}, other_products)) << std::endl;
std::array<int, 5> ar{10, 20, 30, 40, 50};
emit(std::cout, mutate_copy(ar, other_products)) << std::endl;
emit(std::cout, mutate_inplace(ar, other_products)) << std::endl;
auto in = std::vector<int> {10, 11, 12, 13, 14};
emit(std::cout, mutate_copy(in, other_products)) << std::endl;
std::vector<int> foo{};
emit(std::cout, mutate_inplace(foo, other_products)) << std::endl;
}
previous code: