permutation.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2014-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. //===-------------------------- algorithm ---------------------------------===//
  14. //
  15. // The LLVM Compiler Infrastructure
  16. //
  17. // This file is dual licensed under the MIT and the University of Illinois Open
  18. // Source Licenses. See LICENSE.TXT for details.
  19. //
  20. //===----------------------------------------------------------------------===//
  21. #ifndef RANGES_V3_ALGORITHM_PERMUTATION_HPP
  22. #define RANGES_V3_ALGORITHM_PERMUTATION_HPP
  23. #include <meta/meta.hpp>
  24. #include <range/v3/range_fwd.hpp>
  25. #include <range/v3/algorithm/mismatch.hpp>
  26. #include <range/v3/algorithm/reverse.hpp>
  27. #include <range/v3/functional/comparisons.hpp>
  28. #include <range/v3/functional/identity.hpp>
  29. #include <range/v3/functional/invoke.hpp>
  30. #include <range/v3/iterator/concepts.hpp>
  31. #include <range/v3/iterator/operations.hpp>
  32. #include <range/v3/iterator/traits.hpp>
  33. #include <range/v3/range/access.hpp>
  34. #include <range/v3/range/concepts.hpp>
  35. #include <range/v3/range/traits.hpp>
  36. #include <range/v3/utility/static_const.hpp>
  37. #include <range/v3/utility/swap.hpp>
  38. #include <range/v3/detail/prologue.hpp>
  39. namespace ranges
  40. {
  41. /// \addtogroup group-algorithms
  42. /// @{
  43. /// \cond
  44. namespace detail
  45. {
  46. template<typename I1, typename S1, typename I2, typename S2, typename C,
  47. typename P1, typename P2>
  48. constexpr bool is_permutation_impl(I1 begin1,
  49. S1 end1,
  50. I2 begin2,
  51. S2 end2,
  52. C pred,
  53. P1 proj1,
  54. P2 proj2)
  55. {
  56. // shorten sequences as much as possible by lopping off any equal parts
  57. const auto mismatch =
  58. ranges::mismatch(begin1, end1, begin2, end2, pred, proj1, proj2);
  59. begin1 = mismatch.in1;
  60. begin2 = mismatch.in2;
  61. if(begin1 == end1 || begin2 == end2)
  62. {
  63. return begin1 == end1 && begin2 == end2;
  64. }
  65. // begin1 != end1 && begin2 != end2 && *begin1 != *begin2
  66. auto l1 = distance(begin1, end1);
  67. auto l2 = distance(begin2, end2);
  68. if(l1 != l2)
  69. return false;
  70. // For each element in [f1, l1) see if there are the same number of
  71. // equal elements in [f2, l2)
  72. for(I1 i = begin1; i != end1; ++i)
  73. {
  74. // Have we already counted the number of *i in [f1, l1)?
  75. const auto should_continue = [&] {
  76. for(I1 j = begin1; j != i; ++j)
  77. if(invoke(pred, invoke(proj1, *j), invoke(proj1, *i)))
  78. return true;
  79. return false;
  80. }();
  81. if(should_continue)
  82. {
  83. continue;
  84. }
  85. // Count number of *i in [f2, l2)
  86. iter_difference_t<I2> c2 = 0;
  87. for(I2 j = begin2; j != end2; ++j)
  88. if(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))
  89. ++c2;
  90. if(c2 == 0)
  91. return false;
  92. // Count number of *i in [i, l1) (we can start with 1)
  93. iter_difference_t<I1> c1 = 1;
  94. for(I1 j = next(i); j != end1; ++j)
  95. if(invoke(pred, invoke(proj1, *i), invoke(proj1, *j)))
  96. ++c1;
  97. if(c1 != c2)
  98. return false;
  99. }
  100. return true;
  101. }
  102. } // namespace detail
  103. /// \endcond
  104. RANGES_FUNC_BEGIN(is_permutation)
  105. /// \brief function template \c is_permutation
  106. template(typename I1,
  107. typename S1,
  108. typename I2,
  109. typename C = equal_to,
  110. typename P1 = identity,
  111. typename P2 = identity)(
  112. requires forward_iterator<I1> AND sentinel_for<S1, I1> AND
  113. forward_iterator<I2> AND indirectly_comparable<I1, I2, C, P1, P2>)
  114. RANGES_DEPRECATED(
  115. "Use the variant of ranges::is_permutation that takes an upper bound "
  116. "for both sequences")
  117. bool RANGES_FUNC(is_permutation)(I1 begin1,
  118. S1 end1,
  119. I2 begin2,
  120. C pred = C{},
  121. P1 proj1 = P1{},
  122. P2 proj2 = P2{}) //
  123. {
  124. // shorten sequences as much as possible by lopping off any equal parts
  125. for(; begin1 != end1; ++begin1, ++begin2)
  126. if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
  127. goto not_done;
  128. return true;
  129. not_done:
  130. // begin1 != end1 && *begin1 != *begin2
  131. auto l1 = distance(begin1, end1);
  132. if(l1 == 1)
  133. return false;
  134. I2 end2 = next(begin2, l1);
  135. // For each element in [f1, l1) see if there are the same number of
  136. // equal elements in [f2, l2)
  137. for(I1 i = begin1; i != end1; ++i)
  138. {
  139. // Have we already counted the number of *i in [f1, l1)?
  140. for(I1 j = begin1; j != i; ++j)
  141. if(invoke(pred, invoke(proj1, *j), invoke(proj1, *i)))
  142. goto next_iter;
  143. {
  144. // Count number of *i in [f2, l2)
  145. iter_difference_t<I2> c2 = 0;
  146. for(I2 j = begin2; j != end2; ++j)
  147. if(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))
  148. ++c2;
  149. if(c2 == 0)
  150. return false;
  151. // Count number of *i in [i, l1) (we can start with 1)
  152. iter_difference_t<I1> c1 = 1;
  153. for(I1 j = next(i); j != end1; ++j)
  154. if(invoke(pred, invoke(proj1, *i), invoke(proj1, *j)))
  155. ++c1;
  156. if(c1 != c2)
  157. return false;
  158. }
  159. next_iter:;
  160. }
  161. return true;
  162. }
  163. /// \overload
  164. template(typename I1,
  165. typename S1,
  166. typename I2,
  167. typename S2,
  168. typename C = equal_to,
  169. typename P1 = identity,
  170. typename P2 = identity)(
  171. requires forward_iterator<I1> AND sentinel_for<S1, I1> AND
  172. forward_iterator<I2> AND sentinel_for<S2, I2> AND
  173. indirectly_comparable<I1, I2, C, P1, P2>)
  174. constexpr bool RANGES_FUNC(is_permutation)(I1 begin1,
  175. S1 end1,
  176. I2 begin2,
  177. S2 end2,
  178. C pred = C{},
  179. P1 proj1 = P1{},
  180. P2 proj2 = P2{}) //
  181. {
  182. if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S1, I1> &&
  183. sized_sentinel_for<S2, I2>))
  184. {
  185. RANGES_DIAGNOSTIC_PUSH
  186. RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
  187. return distance(begin1, end1) == distance(begin2, end2) &&
  188. (*this)(std::move(begin1),
  189. std::move(end1),
  190. std::move(begin2),
  191. std::move(pred),
  192. std::move(proj1),
  193. std::move(proj2));
  194. RANGES_DIAGNOSTIC_POP
  195. }
  196. return detail::is_permutation_impl(std::move(begin1),
  197. std::move(end1),
  198. std::move(begin2),
  199. std::move(end2),
  200. std::move(pred),
  201. std::move(proj1),
  202. std::move(proj2));
  203. }
  204. /// \overload
  205. template(typename Rng1,
  206. typename I2Ref,
  207. typename C = equal_to,
  208. typename P1 = identity,
  209. typename P2 = identity)(
  210. requires forward_range<Rng1> AND forward_iterator<uncvref_t<I2Ref>> AND
  211. indirectly_comparable<iterator_t<Rng1>, uncvref_t<I2Ref>, C, P1, P2>)
  212. RANGES_DEPRECATED(
  213. "Use the variant of ranges::is_permutation that takes an upper bound "
  214. "for both sequences")
  215. bool RANGES_FUNC(is_permutation)(Rng1 && rng1,
  216. I2Ref && begin2,
  217. C pred = C{},
  218. P1 proj1 = P1{},
  219. P2 proj2 = P2{}) //
  220. {
  221. RANGES_DIAGNOSTIC_PUSH
  222. RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
  223. return (*this)(begin(rng1),
  224. end(rng1),
  225. (I2Ref &&) begin2,
  226. std::move(pred),
  227. std::move(proj1),
  228. std::move(proj2));
  229. RANGES_DIAGNOSTIC_POP
  230. }
  231. /// \overload
  232. template(typename Rng1,
  233. typename Rng2,
  234. typename C = equal_to,
  235. typename P1 = identity,
  236. typename P2 = identity)(
  237. requires forward_range<Rng1> AND forward_range<Rng2> AND
  238. indirectly_comparable<iterator_t<Rng1>, iterator_t<Rng2>, C, P1, P2>)
  239. constexpr bool RANGES_FUNC(is_permutation)(
  240. Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) //
  241. {
  242. if(RANGES_CONSTEXPR_IF(sized_range<Rng1> && sized_range<Rng2>))
  243. {
  244. RANGES_DIAGNOSTIC_PUSH
  245. RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
  246. return distance(rng1) == distance(rng2) && (*this)(begin(rng1),
  247. end(rng1),
  248. begin(rng2),
  249. std::move(pred),
  250. std::move(proj1),
  251. std::move(proj2));
  252. RANGES_DIAGNOSTIC_POP
  253. }
  254. return detail::is_permutation_impl(begin(rng1),
  255. end(rng1),
  256. begin(rng2),
  257. end(rng2),
  258. std::move(pred),
  259. std::move(proj1),
  260. std::move(proj2));
  261. }
  262. RANGES_FUNC_END(is_permutation)
  263. RANGES_FUNC_BEGIN(next_permutation)
  264. /// \brief function template \c next_permutation
  265. template(typename I, typename S, typename C = less, typename P = identity)(
  266. requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
  267. sortable<I, C, P>)
  268. constexpr bool RANGES_FUNC(next_permutation)(I first, S end_, C pred = C{}, P proj = P{}) //
  269. {
  270. if(first == end_)
  271. return false;
  272. I last = ranges::next(first, end_), i = last;
  273. if(first == --i)
  274. return false;
  275. while(true)
  276. {
  277. I ip1 = i;
  278. if(invoke(pred, invoke(proj, *--i), invoke(proj, *ip1)))
  279. {
  280. I j = last;
  281. while(!invoke(pred, invoke(proj, *i), invoke(proj, *--j)))
  282. ;
  283. ranges::iter_swap(i, j);
  284. ranges::reverse(ip1, last);
  285. return true;
  286. }
  287. if(i == first)
  288. {
  289. ranges::reverse(first, last);
  290. return false;
  291. }
  292. }
  293. }
  294. /// \overload
  295. template(typename Rng, typename C = less, typename P = identity)(
  296. requires bidirectional_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
  297. constexpr bool RANGES_FUNC(next_permutation)(Rng && rng, C pred = C{}, P proj = P{}) //
  298. {
  299. return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
  300. }
  301. RANGES_FUNC_END(next_permutation)
  302. RANGES_FUNC_BEGIN(prev_permutation)
  303. /// \brief function template \c prev_permutation
  304. template(typename I, typename S, typename C = less, typename P = identity)(
  305. requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
  306. sortable<I, C, P>)
  307. constexpr bool RANGES_FUNC(prev_permutation)(I first, S end_, C pred = C{}, P proj = P{}) //
  308. {
  309. if(first == end_)
  310. return false;
  311. I last = ranges::next(first, end_), i = last;
  312. if(first == --i)
  313. return false;
  314. while(true)
  315. {
  316. I ip1 = i;
  317. if(invoke(pred, invoke(proj, *ip1), invoke(proj, *--i)))
  318. {
  319. I j = last;
  320. while(!invoke(pred, invoke(proj, *--j), invoke(proj, *i)))
  321. ;
  322. ranges::iter_swap(i, j);
  323. ranges::reverse(ip1, last);
  324. return true;
  325. }
  326. if(i == first)
  327. {
  328. ranges::reverse(first, last);
  329. return false;
  330. }
  331. }
  332. }
  333. /// \overload
  334. template(typename Rng, typename C = less, typename P = identity)(
  335. requires bidirectional_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
  336. constexpr bool RANGES_FUNC(prev_permutation)(Rng && rng, C pred = C{}, P proj = P{}) //
  337. {
  338. return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
  339. }
  340. RANGES_FUNC_END(prev_permutation)
  341. namespace cpp20
  342. {
  343. using ranges::is_permutation;
  344. using ranges::next_permutation;
  345. using ranges::prev_permutation;
  346. } // namespace cpp20
  347. /// @}
  348. } // namespace ranges
  349. #include <range/v3/detail/epilogue.hpp>
  350. #endif