is_permutation.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___ALGORITHM_IS_PERMUTATION_H
  10. #define _LIBCPP___ALGORITHM_IS_PERMUTATION_H
  11. #include <__algorithm/comp.h>
  12. #include <__config>
  13. #include <__iterator/distance.h>
  14. #include <__iterator/iterator_traits.h>
  15. #include <__iterator/next.h>
  16. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  17. # pragma GCC system_header
  18. #endif
  19. _LIBCPP_BEGIN_NAMESPACE_STD
  20. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  21. _LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
  22. is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  23. _BinaryPredicate __pred) {
  24. // shorten sequences as much as possible by lopping of any equal prefix
  25. for (; __first1 != __last1; ++__first1, (void)++__first2)
  26. if (!__pred(*__first1, *__first2))
  27. break;
  28. if (__first1 == __last1)
  29. return true;
  30. // __first1 != __last1 && *__first1 != *__first2
  31. typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1;
  32. _D1 __l1 = _VSTD::distance(__first1, __last1);
  33. if (__l1 == _D1(1))
  34. return false;
  35. _ForwardIterator2 __last2 = _VSTD::next(__first2, __l1);
  36. // For each element in [f1, l1) see if there are the same number of
  37. // equal elements in [f2, l2)
  38. for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) {
  39. // Have we already counted the number of *__i in [f1, l1)?
  40. _ForwardIterator1 __match = __first1;
  41. for (; __match != __i; ++__match)
  42. if (__pred(*__match, *__i))
  43. break;
  44. if (__match == __i) {
  45. // Count number of *__i in [f2, l2)
  46. _D1 __c2 = 0;
  47. for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
  48. if (__pred(*__i, *__j))
  49. ++__c2;
  50. if (__c2 == 0)
  51. return false;
  52. // Count number of *__i in [__i, l1) (we can start with 1)
  53. _D1 __c1 = 1;
  54. for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j)
  55. if (__pred(*__i, *__j))
  56. ++__c1;
  57. if (__c1 != __c2)
  58. return false;
  59. }
  60. }
  61. return true;
  62. }
  63. template <class _ForwardIterator1, class _ForwardIterator2>
  64. _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
  65. is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
  66. typedef typename iterator_traits<_ForwardIterator1>::value_type __v1;
  67. typedef typename iterator_traits<_ForwardIterator2>::value_type __v2;
  68. return _VSTD::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>());
  69. }
  70. #if _LIBCPP_STD_VER > 11
  71. template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2>
  72. _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
  73. __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  74. _ForwardIterator2 __last2, _BinaryPredicate __pred, forward_iterator_tag, forward_iterator_tag) {
  75. // shorten sequences as much as possible by lopping of any equal prefix
  76. for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2)
  77. if (!__pred(*__first1, *__first2))
  78. break;
  79. if (__first1 == __last1)
  80. return __first2 == __last2;
  81. else if (__first2 == __last2)
  82. return false;
  83. typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1;
  84. _D1 __l1 = _VSTD::distance(__first1, __last1);
  85. typedef typename iterator_traits<_ForwardIterator2>::difference_type _D2;
  86. _D2 __l2 = _VSTD::distance(__first2, __last2);
  87. if (__l1 != __l2)
  88. return false;
  89. // For each element in [f1, l1) see if there are the same number of
  90. // equal elements in [f2, l2)
  91. for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) {
  92. // Have we already counted the number of *__i in [f1, l1)?
  93. _ForwardIterator1 __match = __first1;
  94. for (; __match != __i; ++__match)
  95. if (__pred(*__match, *__i))
  96. break;
  97. if (__match == __i) {
  98. // Count number of *__i in [f2, l2)
  99. _D1 __c2 = 0;
  100. for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
  101. if (__pred(*__i, *__j))
  102. ++__c2;
  103. if (__c2 == 0)
  104. return false;
  105. // Count number of *__i in [__i, l1) (we can start with 1)
  106. _D1 __c1 = 1;
  107. for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j)
  108. if (__pred(*__i, *__j))
  109. ++__c1;
  110. if (__c1 != __c2)
  111. return false;
  112. }
  113. }
  114. return true;
  115. }
  116. template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>
  117. _LIBCPP_CONSTEXPR_AFTER_CXX17 bool __is_permutation(_RandomAccessIterator1 __first1, _RandomAccessIterator2 __last1,
  118. _RandomAccessIterator1 __first2, _RandomAccessIterator2 __last2,
  119. _BinaryPredicate __pred, random_access_iterator_tag,
  120. random_access_iterator_tag) {
  121. if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2))
  122. return false;
  123. return _VSTD::is_permutation<_RandomAccessIterator1, _RandomAccessIterator2,
  124. _BinaryPredicate&>(__first1, __last1, __first2, __pred);
  125. }
  126. template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
  127. _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
  128. is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  129. _ForwardIterator2 __last2, _BinaryPredicate __pred) {
  130. return _VSTD::__is_permutation<_BinaryPredicate&>(
  131. __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(),
  132. typename iterator_traits<_ForwardIterator2>::iterator_category());
  133. }
  134. template <class _ForwardIterator1, class _ForwardIterator2>
  135. _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
  136. is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
  137. _ForwardIterator2 __last2) {
  138. typedef typename iterator_traits<_ForwardIterator1>::value_type __v1;
  139. typedef typename iterator_traits<_ForwardIterator2>::value_type __v2;
  140. return _VSTD::__is_permutation(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(),
  141. typename iterator_traits<_ForwardIterator1>::iterator_category(),
  142. typename iterator_traits<_ForwardIterator2>::iterator_category());
  143. }
  144. #endif
  145. _LIBCPP_END_NAMESPACE_STD
  146. #endif // _LIBCPP___ALGORITHM_IS_PERMUTATION_H