Iros
 
Loading...
Searching...
No Matches
is_permutation.h
Go to the documentation of this file.
1#pragma once
2
10
11namespace di::container {
12namespace detail {
14 template<concepts::ForwardIterator It1, concepts::SentinelFor<It1> Sent1, concepts::ForwardIterator It2,
15 concepts::SentinelFor<It2> Sent2, typename Proj1 = function::Identity,
16 typename Proj2 = function::Identity,
17 concepts::IndirectEquivalenceRelation<meta::Projected<It1, Sent1>, meta::Projected<It2, Sent2>> Pred =
18 function::Equal>
19 constexpr auto operator()(It1 first1, Sent1 sent1, It2 first2, Sent2 sent2, Pred pred = {}, Proj1 proj1 = {},
20 Proj2 proj2 = {}) const -> bool {
21 if (container::distance(first1, sent1) != container::distance(first2, sent2)) {
22 return false;
23 }
24 return is_permutation_same_sized(util::move(first1), sent1, util::move(first2), sent2, util::ref(pred),
25 util::ref(proj1), util::ref(proj2));
26 }
27
28 template<concepts::ForwardContainer Con1, concepts::ForwardContainer Con2, typename Proj1 = function::Identity,
29 typename Proj2 = function::Identity,
30 concepts::IndirectEquivalenceRelation<meta::Projected<meta::ContainerIterator<Con1>, Proj1>,
31 meta::Projected<meta::ContainerIterator<Con2>, Proj2>>
32 Pred = function::Equal>
33 constexpr auto operator()(Con1&& container1, Con2&& container2, Pred pred = {}, Proj1 proj1 = {},
34 Proj2 proj2 = {}) const -> bool {
35 if (container::distance(container1) != container::distance(container2)) {
36 return false;
37 }
38 return is_permutation_same_sized(container::begin(container1), container::end(container1),
39 container::begin(container2), container::end(container2), util::ref(pred),
40 util::ref(proj1), util::ref(proj2));
41 }
42
43 private:
44 template<typename It1, typename Sent1, typename It2, typename Sent2, typename Proj1, typename Proj2,
45 typename Pred>
46 constexpr static auto is_permutation_same_sized(It1 first1, Sent1 sent1, It2 first2, Sent2 sent2, Pred pred,
47 Proj1 proj1, Proj2 proj2) -> bool {
48 // Skip any part where the 2 containers are identical.
49 auto [left, right] = container::mismatch(util::move(first1), sent1, util::move(first2), sent2,
50 util::ref(pred), util::ref(proj1), util::ref(proj2));
51
52 for (auto it = left; it != sent1; ++it) {
53 auto compare_to_current = [&]<typename T>(T&& value) -> bool {
54 return function::invoke(pred, function::invoke(proj1, *it), util::forward<T>(value));
55 };
56
57 // This element has already been checked, so skip it this round.
58 if (it != container::find_if(left, it, compare_to_current, proj1)) {
59 continue;
60 }
61
62 // Now ensure that the count of elements of *it in [left, sent1)
63 // is the same as the count of elements of *it in [right, sent2].
64 auto count_right = container::count_if(right, sent2, compare_to_current, util::ref(proj2));
65 if (count_right == 0 ||
66 count_right != container::count_if(it, sent1, compare_to_current, util::ref(proj1))) {
67 return false;
68 }
69 }
70 return true;
71 }
72 };
73}
74
76}
77
78namespace di {
80}
Definition sequence.h:13
Definition sequence.h:12
constexpr auto is_permutation
Definition is_permutation.h:75
constexpr auto find_if
Definition find_if.h:31
constexpr auto distance
Definition distance.h:44
constexpr auto mismatch
Definition mismatch.h:40
constexpr auto end
Definition end.h:47
constexpr auto count_if
Definition count_if.h:33
constexpr auto begin
Definition begin.h:44
constexpr auto invoke
Definition invoke.h:100
constexpr auto value
Definition value.h:34
constexpr auto ref
Definition reference_wrapper.h:98
Definition zstring_parser.h:9
@ T
Definition key.h:29
Definition is_permutation.h:13
constexpr auto operator()(It1 first1, Sent1 sent1, It2 first2, Sent2 sent2, Pred pred={}, Proj1 proj1={}, Proj2 proj2={}) const -> bool
Definition is_permutation.h:19
constexpr auto operator()(Con1 &&container1, Con2 &&container2, Pred pred={}, Proj1 proj1={}, Proj2 proj2={}) const -> bool
Definition is_permutation.h:33