tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
is_permutation.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2019 Tobias Hienzsch
3
4#ifndef TETL_ALGORITHM_IS_PERMUTATION_HPP
5#define TETL_ALGORITHM_IS_PERMUTATION_HPP
6
7#include <etl/_algorithm/count.hpp>
8#include <etl/_algorithm/find.hpp>
9#include <etl/_algorithm/mismatch.hpp>
10#include <etl/_iterator/distance.hpp>
11#include <etl/_iterator/iterator_traits.hpp>
12#include <etl/_iterator/next.hpp>
13#include <etl/_iterator/tags.hpp>
14#include <etl/_type_traits/is_base_of.hpp>
15
16namespace etl {
17
18/// \brief Returns true if there exists a permutation of the elements in the
19/// range `[first1, last1)` that makes that range equal to the range `[first2,
20/// last2)`, where `last2` denotes `first2 + (last1 - first1)` if it was not
21/// given.
22/// \ingroup algorithm
23template <typename ForwardIt1, typename ForwardIt2>
24[[nodiscard]] constexpr auto is_permutation(ForwardIt1 first, ForwardIt1 last, ForwardIt2 first2) -> bool
25{
26 // skip common prefix
27 auto const [fDiff1, fDiff2] = etl::mismatch(first, last, first2);
28
29 // iterate over the rest, counting how many times each element
30 // from `[first, last)` appears in [first2, last2)
31 if (fDiff1 != last) {
32 auto last2 = etl::next(fDiff2, etl::distance(fDiff1, last));
33 for (auto i = fDiff1; i != last; ++i) {
34 // this *i has been checked
35 if (i != etl::find(fDiff1, i, *i)) {
36 continue;
37 }
38
39 auto m = etl::count(fDiff2, last2, *i);
40 if (m == 0 or etl::count(i, last, *i) != m) {
41 return false;
42 }
43 }
44 }
45
46 return true;
47}
48
49/// \ingroup algorithm
50template <typename ForwardIt1, typename ForwardIt2>
51[[nodiscard]] constexpr auto is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2)
52 -> bool
53{
55
56 constexpr auto lhsIsRandomIt = is_base_of_v<tag, typename iterator_traits<ForwardIt1>::iterator_category>;
57 constexpr auto rhsIsRandomIt = is_base_of_v<tag, typename iterator_traits<ForwardIt2>::iterator_category>;
58
59 if constexpr (lhsIsRandomIt and rhsIsRandomIt) {
60 if (etl::distance(first1, last1) != etl::distance(first2, last2)) {
61 return false;
62 }
63 }
64 return etl::is_permutation(first1, last1, first2);
65}
66
67} // namespace etl
68
69#endif // TETL_ALGORITHM_IS_PERMUTATION_HPP
constexpr auto is_permutation(ForwardIt1 first, ForwardIt1 last, ForwardIt2 first2) -> bool
Returns true if there exists a permutation of the elements in the range [first1, last1) that makes th...
Definition is_permutation.hpp:24
constexpr auto is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2) -> bool
Definition is_permutation.hpp:51
Definition adjacent_find.hpp:9
iterator_traits is the type trait class that provides uniform interface to the properties of LegacyIt...
Definition iterator_traits.hpp:48
Defines the category of an iterator. Each tag is an empty type and corresponds to one of the five (un...
Definition tags.hpp:37