std::ranges::is_permutation
| Défini dans l'en-tête <algorithm>
|
||
| Signature d'appel |
||
template< std::forward_iterator I1, std::sentinel_for<I1> S1,
std::forward_iterator I2, std::sentinel_for<I2> S2,
class Proj1 = std::identity, class Proj2 = std::identity,
std::indirect_equivalence_relation<std::projected<I1, Proj1>,
std::projected<I2, Proj2>>
Pred = ranges::equal_to >
constexpr bool
is_permutation( I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
|
(1) | (depuis C++20) |
template< ranges::forward_range R1, ranges::forward_range R2,
class Proj1 = std::identity, class Proj2 = std::identity,
std::indirect_equivalence_relation<
std::projected<ranges::iterator_t<R1>, Proj1>,
std::projected<ranges::iterator_t<R2>, Proj2>>
Pred = ranges::equal_to >
constexpr bool
is_permutation( R1&& r1, R2&& r2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
|
(2) | (depuis C++20) |
true s'il existe une permutation des éléments de l'intervalle [first1, last1) qui rend l'intervalle égal à [first2, last2) (après application des projections correspondantes Proj1, Proj2, et en utilisant le prédicat binaire Pred comme comparateur). Sinon, renvoie false.r1 comme première intervalle source et r2 comme seconde intervalle source, comme si on utilisait ranges::begin(r1) comme first1, ranges::end(r1) comme last1, ranges::begin(r2) comme first2, et ranges::end(r2) comme last2.Les entités de type fonction décrites sur cette page sont des objets de fonction d'algorithme (informellement appelés niebloids), c'est-à-dire :
- Les listes explicites d'arguments de modèle ne peuvent pas être spécifiées lors de l'appel de l'un d'eux.
- Aucun d'eux n'est visible par la recherche dépendante des arguments.
- Lorsque l'un d'eux est trouvé par recherche non qualifiée normale comme le nom à gauche de l'opérateur d'appel de fonction, la recherche dépendante des arguments est inhibée.
Paramètres
| first1, last1 | - | la paire itérateur-sentinelle définissant la première plage d'éléments |
| first2, last2 | - | la paire itérateur-sentinelle définissant la seconde plage d'éléments |
| r1 | - |
la première
range
des éléments
|
| r2 | - |
la seconde
range
des éléments
|
| pred | - | prédicat à appliquer aux éléments projetés |
| proj1 | - | projection à appliquer aux éléments de la première plage |
| proj2 | - | projection à appliquer aux éléments de la seconde plage |
Valeur de retour
true
si la plage
[
first1
,
last1
)
est une permutation de la plage
[
first2
,
last2
)
.
Complexité
Au plus O(N 2 ) applications du prédicat et de chaque projection, ou exactement N si les séquences sont déjà égales, où N est ranges:: distance ( first1, last1 ) . Cependant si ranges:: distance ( first1, last1 ) ! = ranges:: distance ( first2, last2 ) , aucune application du prédicat et des projections n'est effectuée.
Notes
La permutation est une relation d'équivalence .
La
ranges::is_permutation
peut être utilisée dans les tests, par exemple pour vérifier l'exactitude des algorithmes de réarrangement tels que le tri, le mélange, la partition. Si
p
est une séquence originale et
q
est une séquence "mutée", alors
ranges
::
is_permutation
(
p, q
)
==
true
signifie que
q
est constituée des "mêmes" éléments (éventuellement permutés) que
p
.
Implémentation possible
struct is_permutation_fn { template<std::forward_iterator I1, std::sentinel_for<I1> S1, std::forward_iterator I2, std::sentinel_for<I2> S2, class Proj1 = std::identity, class Proj2 = std::identity, std::indirect_equivalence_relation<std::projected<I1, Proj1>, std::projected<I2, Proj2>> Pred = ranges::equal_to> constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { // ignorer le préfixe commun auto ret = std::ranges::mismatch(first1, last1, first2, last2, std::ref(pred), std::ref(proj1), std::ref(proj2)); first1 = ret.in1, first2 = ret.in2; // itérer sur le reste, en comptant combien de fois chaque élément // de [first1, last1) apparaît dans [first2, last2) for (auto i {first1}; i != last1; ++i) { const auto i_proj {std::invoke(proj1, *i)}; auto i_cmp = [&]<typename T>(T&& t) { return std::invoke(pred, i_proj, std::forward<T>(t)); }; if (i != ranges::find_if(first1, i, i_cmp, proj1)) continue; // ce *i a été vérifié if (const auto m {ranges::count_if(first2, last2, i_cmp, proj2)}; m == 0 or m != ranges::count_if(i, last1, i_cmp, proj1)) return false; } return true; } template<ranges::forward_range R1, ranges::forward_range R2, class Proj1 = std::identity, class Proj2 = std::identity, std::indirect_equivalence_relation< std::projected<ranges::iterator_t<R1>, Proj1>, std::projected<ranges::iterator_t<R2>, Proj2>> Pred = ranges::equal_to> constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), std::move(pred), std::move(proj1), std::move(proj2)); } }; inline constexpr is_permutation_fn is_permutation {}; |
Exemple
#include <algorithm> #include <array> #include <cmath> #include <iostream> #include <ranges> auto& operator<<(auto& os, std::ranges::forward_range auto const& v) { os << "{ "; for (const auto& e : v) os << e << ' '; return os << "}"; } int main() { static constexpr auto r1 = {1, 2, 3, 4, 5}; static constexpr auto r2 = {3, 5, 4, 1, 2}; static constexpr auto r3 = {3, 5, 4, 1, 1}; static_assert( std::ranges::is_permutation(r1, r1) && std::ranges::is_permutation(r1, r2) && std::ranges::is_permutation(r2, r1) && std::ranges::is_permutation(r1.begin(), r1.end(), r2.begin(), r2.end())); std::cout << std::boolalpha << "is_permutation(" << r1 << ", " << r2 << "): " << std::ranges::is_permutation(r1, r2) << '\n' << "is_permutation(" << r1 << ", " << r3 << "): " << std::ranges::is_permutation(r1, r3) << '\n' << "is_permutation with custom predicate and projections: " << std::ranges::is_permutation( std::array {-14, -11, -13, -15, -12}, // 1st range std::array {'F', 'E', 'C', 'B', 'D'}, // 2nd range [](int x, int y) { return abs(x) == abs(y); }, // predicate [](int x) { return x + 10; }, // projection for 1st range [](char y) { return int(y - 'A'); }) // projection for 2nd range << '\n'; }
Sortie :
is_permutation({ 1 2 3 4 5 }, { 3 5 4 1 2 }): true
is_permutation({ 1 2 3 4 5 }, { 3 5 4 1 1 }): false
is_permutation with custom predicate and projections: true
Voir aussi
(C++20) |
génère la permutation lexicographique suivante plus grande d'une plage d'éléments (objet fonction d'algorithme) |
(C++20) |
génère la permutation lexicographique suivante plus petite d'une plage d'éléments (objet fonction d'algorithme) |
(C++11) |
détermine si une séquence est une permutation d'une autre séquence (modèle de fonction) |
| génère la permutation lexicographique suivante plus grande d'une plage d'éléments (modèle de fonction & objet fonction d'algorithme) | |
(C++20) |
|
| génère la permutation lexicographique suivante plus petite d'une plage d'éléments (modèle de fonction & objet fonction d'algorithme) | |
(C++20) |
|
(C++20) |
spécifie qu'une relation impose une relation d'équivalence (concept) |