Как применить цепочечно-ассоциативность в C ++ 17 - PullRequest
0 голосов
/ 15 октября 2019
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
  vector<int> v1{1,2,3};
  vector<int> v2{3,2,1};
  vector<int> v3{3,2,1,2};

  int increasing = reduce(v1.begin(), v1.end(), 1, less<int>());
  for_each(v1.begin(), v1.end(),[](int &k){cout<< k <<",";});
  cout << " Increasing? " << increasing << endl;

  increasing = reduce(v2.begin(), v2.end(), 1, less<int>());
  for_each(v2.begin(), v2.end(),[](int &k){cout<< k <<",";});
  cout << " Increasing? " << increasing << endl;

  increasing = reduce(v3.begin(), v3.end(), 1, less<int>());
  for_each(v3.begin(), v3.end(),[](int &k){cout<< k <<",";});
  cout << " Increasing? " << increasing << endl;
}

В этом примере я проверяю векторы, если все их элементы увеличиваются или нет, и вот результаты:

1,2,3, Increasing? 1
3,2,1, Increasing? 0
3,2,1,2, Increasing? 0

Векторы v1 и v2 проходят тесты правильноно v3 нет, потому что функция less<int> по умолчанию применяется как ассоциативно слева , т. е. применяется только к элементу слева.

Для проверки v3 правильно, функция less<int> должна применяться к вектору в целом и AFAIK, что достигается с помощью так называемой цепочечной ассоциативности .

Обратите внимание, что я непросто пытаюсь проверить отсортированную последовательность. Я ищу способ реализовать так называемую ассоциативность цепочек для любой функции, и здесь для примера это less<int>.

Так что я хотел быприменять less<int> как цепочечно-ассоциативный в сжатой форме, т.е. без путаницы в коде. Как я могу это сделать?

Спасибо.

1 Ответ

0 голосов
/ 15 октября 2019

Я понял, что мое первое предложение использовать std::is_sorted() не будет работать в случае двух смежных элементов с одинаковым значением - они отсортированы, но не увеличиваются. Но если вы хотите использовать стандартные алгоритмы и не делать это с помощью рукописного цикла, std::adjacent_find() работает:

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

// Version using an explicit binary predicate
template <class It, class F>
bool increasing(const It beg, const It end, F op) {
  return std::adjacent_find(beg, end, [&op](const auto &a, const auto &b) {
           return !op(a, b);
         }) == end;
}

// Version using <
template <class It> bool increasing(const It beg, const It end) {
  return std::adjacent_find(beg, end, [](const auto &a, const auto &b) {
           return !(a < b);
         }) == end;
}

int main() {
  std::vector<int> v1{1, 2, 3}, v2{3, 2, 1}, v3{3, 2, 1, 2};

  std::cout << std::boolalpha;
  std::cout << "v1 increasing: " << increasing(v1.begin(), v1.end()) << '\n';
  std::cout << "v2 increasing: "
            << increasing(v2.begin(), v2.end(), std::less<int>()) << '\n';
  std::cout << "v3 increasing: " << increasing(v3.begin(), v3.end()) << '\n';
  return 0;
}

дает

v1 increasing: true
v2 increasing: false
v3 increasing: false
...