Namespaces
Variants

std::ranges::is_permutation

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲に対するアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
ソートおよび関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割済み範囲に対して)
集合操作 (ソート済み範囲に対して)
マージ操作 (ソート済み範囲に対して)
ヒープ操作
最小値/最大値操作
(C++11)
(C++17)
辞書順比較操作
順列操作


 
制約付きアルゴリズム
このメニュー内のすべての名前は名前空間 std::ranges
に属します。 非変更シーケンス操作
変更シーケンス操作
分割操作
ソート操作
二分探索操作 (ソート済み範囲に対して)
       
       
集合操作 (ソート済み範囲に対して)
ヒープ操作
最小値/最大値操作
順列操作
畳み込み操作
数値操作
(C++23)            
未初期化記憶域に対する操作
戻り値の型
 
ヘッダ <algorithm>
で定義 関数シグネチャ
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) (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) (C++20以降)
1) 範囲 true の要素に、対応する射影 、 を適用し、二項述語 [first1, last1) を比較器として使用した後、範囲 を に[first2, last2)等しくProj1 するProj2順列Predが存在する場合に false を返す。そうでない場合は
を返す。 2) (1) と同じだが、r1 を最初のソース範囲として、r2 を2番目のソース範囲として使用する。あたかも ranges::begin(r1) を first1 として、ranges::end(r1) を last1 として、ranges::begin(r2) を first2 として、ranges::end(r2) を last2 として使用するかのように動作する。

このページで説明されている関数のようなエンティティは アルゴリズム関数オブジェクト (非公式に niebloids として知られています) であり、以下が適用されます:

  • それらのいずれかを呼び出すときに、明示的なテンプレート引数リストを指定することはできません。
  • それらのいずれも 引数依存の名前探索 からは見えません。
  • それらのいずれかが 通常の非修飾名前探索 によって関数呼び出し演算子の左側の名前として見つかった場合、引数依存の名前探索 は抑制されます。

パラメータ

first1, last1 - 要素の第1 範囲 を定義するイテレータ-番兵ペア
first2, last2 - 要素の第2 範囲 を定義するイテレータ-番兵ペア
r1 - 要素の第1 range
r2 - 要素の第2 range
pred - 投影された要素に適用する述語
proj1 - 第1範囲の要素に適用する投影
proj2 - 第2範囲の要素に適用する投影

戻り値

true を返す条件は、範囲 [ first1 , last1 ) が範囲 [ first2 , last2 ) の順列である場合です。

計算量

最大で O(N 2 ) 回の述語と各射影の適用、またはシーケンスが既に等しい場合は正確に N 回の適用が行われます。ここで N は ranges:: distance ( first1, last1 ) です。 ただし、 ranges:: distance ( first1, last1 ) ! = ranges:: distance ( first2, last2 ) の場合、述語と射影の適用は行われません。

注記

置換関係は 同値関係 です。

ranges::is_permutationは、ソート、シャッフル、パーティショニングなどの並べ替えアルゴリズムの正確性を検証するテストなどに使用できます。pが元のシーケンスでqが「変更された」シーケンスである場合、 ranges :: is_permutation ( p, q ) == true は、qがpと「同じ」要素(順序が変更されている可能性あり)で構成されていることを意味します。

実装例

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
    {
        // 共通プレフィックスをスキップ
        auto ret = std::ranges::mismatch(first1, last1, first2, last2,
                                         std::ref(pred), std::ref(proj1), std::ref(proj2));
        first1 = ret.in1, first2 = ret.in2;
        // 残りの要素を反復処理し、各要素が何回出現するかをカウントする
        // [first1, last1) が [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; // この *i はチェック済み
            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 {};

例

#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';
}

出力:

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

関連項目

範囲の要素の辞書順で次の順列を生成する
(アルゴリズム関数オブジェクト)
範囲の要素の辞書順で前の順列を生成する
(アルゴリズム関数オブジェクト)
あるシーケンスが別のシーケンスの置換であるか判定する
(関数テンプレート)
範囲の要素の辞書順で次の順列を生成する
(関数テンプレート&アルゴリズム関数オブジェクト)
範囲の要素の辞書順で前の順列を生成する
(関数テンプレート&アルゴリズム関数オブジェクト)
関係が同値関係を課すことを指定する
(コンセプト)