algorithm.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. #pragma once
  2. #include "is_in.h"
  3. #include "utility.h"
  4. #include <util/system/defaults.h>
  5. #include <util/generic/fwd.h>
  6. #include <numeric>
  7. #include <algorithm>
  8. #include <iterator>
  9. #include <utility>
  10. namespace NPrivate {
  11. template <class I, class F, class P>
  12. constexpr I ExtremeElementBy(I begin, I end, F&& func, P&& pred) {
  13. if (begin == end) {
  14. return end;
  15. }
  16. auto bestValue = func(*begin);
  17. auto bestPos = begin;
  18. for (auto i = ++begin; i != end; ++i) {
  19. auto curValue = func(*i);
  20. if (pred(curValue, bestValue)) {
  21. bestValue = curValue;
  22. bestPos = i;
  23. }
  24. }
  25. return bestPos;
  26. }
  27. }
  28. template <class T>
  29. constexpr void Sort(T f, T l) {
  30. std::sort(f, l);
  31. }
  32. template <class T, class C>
  33. constexpr void Sort(T f, T l, C c) {
  34. std::sort(f, l, c);
  35. }
  36. template <class TContainer>
  37. constexpr void Sort(TContainer& container) {
  38. Sort(container.begin(), container.end());
  39. }
  40. template <class TContainer, typename TCompare>
  41. constexpr void Sort(TContainer& container, TCompare compare) {
  42. Sort(container.begin(), container.end(), compare);
  43. }
  44. template <class TIterator, typename TGetKey>
  45. constexpr void SortBy(TIterator begin, TIterator end, const TGetKey& getKey) {
  46. Sort(begin, end, [&](auto&& left, auto&& right) { return getKey(left) < getKey(right); });
  47. }
  48. template <class TContainer, typename TGetKey>
  49. constexpr void SortBy(TContainer& container, const TGetKey& getKey) {
  50. SortBy(container.begin(), container.end(), getKey);
  51. }
  52. template <class T>
  53. static inline void StableSort(T f, T l) {
  54. std::stable_sort(f, l);
  55. }
  56. template <class T, class C>
  57. static inline void StableSort(T f, T l, C c) {
  58. std::stable_sort(f, l, c);
  59. }
  60. template <class TContainer>
  61. static inline void StableSort(TContainer& container) {
  62. StableSort(container.begin(), container.end());
  63. }
  64. template <class TContainer, typename TCompare>
  65. static inline void StableSort(TContainer& container, TCompare compare) {
  66. StableSort(container.begin(), container.end(), compare);
  67. }
  68. template <class TIterator, typename TGetKey>
  69. static inline void StableSortBy(TIterator begin, TIterator end, const TGetKey& getKey) {
  70. StableSort(begin, end, [&](auto&& left, auto&& right) { return getKey(left) < getKey(right); });
  71. }
  72. template <class TContainer, typename TGetKey>
  73. static inline void StableSortBy(TContainer& container, const TGetKey& getKey) {
  74. StableSortBy(container.begin(), container.end(), getKey);
  75. }
  76. template <class T>
  77. constexpr void PartialSort(T f, T m, T l) {
  78. std::partial_sort(f, m, l);
  79. }
  80. template <class T, class C>
  81. constexpr void PartialSort(T f, T m, T l, C c) {
  82. std::partial_sort(f, m, l, c);
  83. }
  84. template <class T, class R>
  85. constexpr R PartialSortCopy(T f, T l, R of, R ol) {
  86. return std::partial_sort_copy(f, l, of, ol);
  87. }
  88. template <class T, class R, class C>
  89. constexpr R PartialSortCopy(T f, T l, R of, R ol, C c) {
  90. return std::partial_sort_copy(f, l, of, ol, c);
  91. }
  92. template <class I, class T>
  93. constexpr I Find(I f, I l, const T& v) {
  94. return std::find(f, l, v);
  95. }
  96. template <class C, class T>
  97. constexpr auto Find(C&& c, const T& v) {
  98. using std::begin;
  99. using std::end;
  100. return std::find(begin(c), end(c), v);
  101. }
  102. // FindPtr - return NULL if not found. Works for arrays, containers, iterators
  103. template <class I, class T>
  104. constexpr auto FindPtr(I f, I l, const T& v) -> decltype(&*f) {
  105. I found = Find(f, l, v);
  106. return (found != l) ? &*found : nullptr;
  107. }
  108. template <class C, class T>
  109. constexpr auto FindPtr(C&& c, const T& v) {
  110. using std::begin;
  111. using std::end;
  112. return FindPtr(begin(c), end(c), v);
  113. }
  114. template <class I, class P>
  115. constexpr I FindIf(I f, I l, P p) {
  116. return std::find_if(f, l, p);
  117. }
  118. template <class C, class P>
  119. constexpr auto FindIf(C&& c, P p) {
  120. using std::begin;
  121. using std::end;
  122. return FindIf(begin(c), end(c), p);
  123. }
  124. template <class I, class P>
  125. constexpr bool AllOf(I f, I l, P pred) {
  126. return std::all_of(f, l, pred);
  127. }
  128. template <class C, class P>
  129. constexpr bool AllOf(const C& c, P pred) {
  130. using std::begin;
  131. using std::end;
  132. return AllOf(begin(c), end(c), pred);
  133. }
  134. template <class I, class P>
  135. constexpr bool AnyOf(I f, I l, P pred) {
  136. return std::any_of(f, l, pred);
  137. }
  138. template <class C, class P>
  139. constexpr bool AnyOf(const C& c, P pred) {
  140. using std::begin;
  141. using std::end;
  142. return AnyOf(begin(c), end(c), pred);
  143. }
  144. // FindIfPtr - return NULL if not found. Works for arrays, containers, iterators
  145. template <class I, class P>
  146. constexpr auto FindIfPtr(I f, I l, P pred) -> decltype(&*f) {
  147. I found = FindIf(f, l, pred);
  148. return (found != l) ? &*found : nullptr;
  149. }
  150. template <class C, class P>
  151. constexpr auto FindIfPtr(C&& c, P pred) {
  152. using std::begin;
  153. using std::end;
  154. return FindIfPtr(begin(c), end(c), pred);
  155. }
  156. template <class C, class T>
  157. constexpr size_t FindIndex(C&& c, const T& x) {
  158. using std::begin;
  159. using std::end;
  160. auto it = Find(begin(c), end(c), x);
  161. return it == end(c) ? NPOS : (it - begin(c));
  162. }
  163. template <class C, class P>
  164. constexpr size_t FindIndexIf(C&& c, P p) {
  165. using std::begin;
  166. using std::end;
  167. auto it = FindIf(begin(c), end(c), p);
  168. return it == end(c) ? NPOS : (it - begin(c));
  169. }
  170. //EqualToOneOf(x, "apple", "orange") means (x == "apple" || x == "orange")
  171. template <typename T>
  172. constexpr bool EqualToOneOf(const T&) {
  173. return false;
  174. }
  175. template <typename T, typename U, typename... Other>
  176. constexpr bool EqualToOneOf(const T& x, const U& y, const Other&... other) {
  177. return x == y || EqualToOneOf(x, other...);
  178. }
  179. template <typename T>
  180. constexpr size_t CountOf(const T&) {
  181. return 0;
  182. }
  183. template <typename T, typename U, typename... Other>
  184. constexpr size_t CountOf(const T& x, const U& y, const Other&... other) {
  185. return static_cast<size_t>(x == y) + CountOf(x, other...);
  186. }
  187. template <class I>
  188. constexpr void PushHeap(I f, I l) {
  189. std::push_heap(f, l);
  190. }
  191. template <class I, class C>
  192. constexpr void PushHeap(I f, I l, C c) {
  193. std::push_heap(f, l, c);
  194. }
  195. template <class I>
  196. constexpr void PopHeap(I f, I l) {
  197. std::pop_heap(f, l);
  198. }
  199. template <class I, class C>
  200. constexpr void PopHeap(I f, I l, C c) {
  201. std::pop_heap(f, l, c);
  202. }
  203. template <class I>
  204. constexpr void MakeHeap(I f, I l) {
  205. std::make_heap(f, l);
  206. }
  207. template <class I, class C>
  208. constexpr void MakeHeap(I f, I l, C c) {
  209. std::make_heap(f, l, c);
  210. }
  211. template <class I>
  212. constexpr void SortHeap(I f, I l) {
  213. std::sort_heap(f, l);
  214. }
  215. template <class I, class C>
  216. constexpr void SortHeap(I f, I l, C c) {
  217. std::sort_heap(f, l, c);
  218. }
  219. template <class I, class T>
  220. constexpr I LowerBound(I f, I l, const T& v) {
  221. return std::lower_bound(f, l, v);
  222. }
  223. template <class I, class T, class C>
  224. constexpr I LowerBound(I f, I l, const T& v, C c) {
  225. return std::lower_bound(f, l, v, c);
  226. }
  227. template <class I, class T, class TGetKey>
  228. constexpr I LowerBoundBy(I f, I l, const T& v, const TGetKey& getKey) {
  229. return std::lower_bound(f, l, v, [&](auto&& left, auto&& right) { return getKey(left) < right; });
  230. }
  231. template <class I, class T>
  232. constexpr I UpperBound(I f, I l, const T& v) {
  233. return std::upper_bound(f, l, v);
  234. }
  235. template <class I, class T, class C>
  236. constexpr I UpperBound(I f, I l, const T& v, C c) {
  237. return std::upper_bound(f, l, v, c);
  238. }
  239. template <class I, class T, class TGetKey>
  240. constexpr I UpperBoundBy(I f, I l, const T& v, const TGetKey& getKey) {
  241. return std::upper_bound(f, l, v, [&](auto&& left, auto&& right) { return left < getKey(right); });
  242. }
  243. template <class T>
  244. constexpr T Unique(T f, T l) {
  245. return std::unique(f, l);
  246. }
  247. template <class T, class P>
  248. constexpr T Unique(T f, T l, P p) {
  249. return std::unique(f, l, p);
  250. }
  251. template <class T, class TGetKey>
  252. constexpr T UniqueBy(T f, T l, const TGetKey& getKey) {
  253. return Unique(f, l, [&](auto&& left, auto&& right) { return getKey(left) == getKey(right); });
  254. }
  255. template <class C>
  256. void SortUnique(C& c) {
  257. Sort(c.begin(), c.end());
  258. c.erase(Unique(c.begin(), c.end()), c.end());
  259. }
  260. template <class C, class Cmp>
  261. void SortUnique(C& c, Cmp cmp) {
  262. Sort(c.begin(), c.end(), cmp);
  263. c.erase(Unique(c.begin(), c.end()), c.end());
  264. }
  265. template <class C, class TGetKey>
  266. void SortUniqueBy(C& c, const TGetKey& getKey) {
  267. SortBy(c, getKey);
  268. c.erase(UniqueBy(c.begin(), c.end(), getKey), c.end());
  269. }
  270. template <class C, class TGetKey>
  271. void StableSortUniqueBy(C& c, const TGetKey& getKey) {
  272. StableSortBy(c, getKey);
  273. c.erase(UniqueBy(c.begin(), c.end(), getKey), c.end());
  274. }
  275. template <class C, class TValue>
  276. void Erase(C& c, const TValue& value) {
  277. c.erase(std::remove(c.begin(), c.end(), value), c.end());
  278. }
  279. template <class C, class P>
  280. void EraseIf(C& c, P p) {
  281. c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
  282. }
  283. template <class C, class P>
  284. void EraseNodesIf(C& c, P p) {
  285. for (auto iter = c.begin(), last = c.end(); iter != last;) {
  286. if (p(*iter)) {
  287. c.erase(iter++);
  288. } else {
  289. ++iter;
  290. }
  291. }
  292. }
  293. template <class T1, class T2>
  294. constexpr bool Equal(T1 f1, T1 l1, T2 f2) {
  295. return std::equal(f1, l1, f2);
  296. }
  297. template <class T1, class T2, class P>
  298. constexpr bool Equal(T1 f1, T1 l1, T2 f2, P p) {
  299. return std::equal(f1, l1, f2, p);
  300. }
  301. template <class TI, class TO>
  302. constexpr TO Copy(TI f, TI l, TO t) {
  303. return std::copy(f, l, t);
  304. }
  305. template <class TI, class TO>
  306. constexpr TO UniqueCopy(TI f, TI l, TO t) {
  307. return std::unique_copy(f, l, t);
  308. }
  309. template <class TI, class TO, class TP>
  310. constexpr TO UniqueCopy(TI f, TI l, TO t, TP p) {
  311. return std::unique_copy(f, l, t, p);
  312. }
  313. template <class TI, class TO, class TP>
  314. constexpr TO RemoveCopyIf(TI f, TI l, TO t, TP p) {
  315. return std::remove_copy_if(f, l, t, p);
  316. }
  317. template <class TI, class TO>
  318. constexpr TO ReverseCopy(TI f, TI l, TO t) {
  319. return std::reverse_copy(f, l, t);
  320. }
  321. template <class TI1, class TI2, class TO>
  322. constexpr TO SetUnion(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p) {
  323. return std::set_union(f1, l1, f2, l2, p);
  324. }
  325. template <class TI1, class TI2, class TO, class TC>
  326. constexpr TO SetUnion(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p, TC c) {
  327. return std::set_union(f1, l1, f2, l2, p, c);
  328. }
  329. template <class TI1, class TI2, class TO>
  330. constexpr TO SetDifference(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p) {
  331. return std::set_difference(f1, l1, f2, l2, p);
  332. }
  333. template <class TI1, class TI2, class TO, class TC>
  334. constexpr TO SetDifference(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p, TC c) {
  335. return std::set_difference(f1, l1, f2, l2, p, c);
  336. }
  337. template <class TI1, class TI2, class TO>
  338. constexpr TO SetSymmetricDifference(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p) {
  339. return std::set_symmetric_difference(f1, l1, f2, l2, p);
  340. }
  341. template <class TI1, class TI2, class TO, class TC>
  342. constexpr TO SetSymmetricDifference(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p, TC c) {
  343. return std::set_symmetric_difference(f1, l1, f2, l2, p, c);
  344. }
  345. template <class TI1, class TI2, class TO>
  346. constexpr TO SetIntersection(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p) {
  347. return std::set_intersection(f1, l1, f2, l2, p);
  348. }
  349. template <class TI1, class TI2, class TO, class TC>
  350. constexpr TO SetIntersection(TI1 f1, TI1 l1, TI2 f2, TI2 l2, TO p, TC c) {
  351. return std::set_intersection(f1, l1, f2, l2, p, c);
  352. }
  353. template <class I, class T>
  354. constexpr void Fill(I f, I l, const T& v) {
  355. std::fill(f, l, v);
  356. }
  357. template <typename I, typename S, typename T>
  358. constexpr I FillN(I f, S n, const T& v) {
  359. return std::fill_n(f, n, v);
  360. }
  361. template <class T>
  362. constexpr void Reverse(T f, T l) {
  363. std::reverse(f, l);
  364. }
  365. template <class T>
  366. constexpr void Rotate(T f, T m, T l) {
  367. std::rotate(f, m, l);
  368. }
  369. template <typename It, typename Val>
  370. constexpr Val Accumulate(It begin, It end, Val val) {
  371. // std::move since C++20
  372. return std::accumulate(begin, end, std::move(val));
  373. }
  374. template <typename It, typename Val, typename BinOp>
  375. constexpr Val Accumulate(It begin, It end, Val val, BinOp binOp) {
  376. // std::move since C++20
  377. return std::accumulate(begin, end, std::move(val), binOp);
  378. }
  379. template <typename C, typename Val>
  380. constexpr Val Accumulate(const C& c, Val val) {
  381. // std::move since C++20
  382. return Accumulate(std::begin(c), std::end(c), std::move(val));
  383. }
  384. template <typename C, typename Val, typename BinOp>
  385. constexpr Val Accumulate(const C& c, Val val, BinOp binOp) {
  386. // std::move since C++20
  387. return Accumulate(std::begin(c), std::end(c), std::move(val), binOp);
  388. }
  389. template <typename It1, typename It2, typename Val>
  390. constexpr Val InnerProduct(It1 begin1, It1 end1, It2 begin2, Val val) {
  391. return std::inner_product(begin1, end1, begin2, val);
  392. }
  393. template <typename It1, typename It2, typename Val, typename BinOp1, typename BinOp2>
  394. constexpr Val InnerProduct(It1 begin1, It1 end1, It2 begin2, Val val, BinOp1 binOp1, BinOp2 binOp2) {
  395. return std::inner_product(begin1, end1, begin2, val, binOp1, binOp2);
  396. }
  397. template <typename TVectorType>
  398. constexpr typename TVectorType::value_type InnerProduct(const TVectorType& lhs, const TVectorType& rhs, typename TVectorType::value_type val = typename TVectorType::value_type()) {
  399. return std::inner_product(lhs.begin(), lhs.end(), rhs.begin(), val);
  400. }
  401. template <typename TVectorType, typename BinOp1, typename BinOp2>
  402. constexpr typename TVectorType::value_type InnerProduct(const TVectorType& lhs, const TVectorType& rhs, typename TVectorType::value_type val, BinOp1 binOp1, BinOp2 binOp2) {
  403. return std::inner_product(lhs.begin(), lhs.end(), rhs.begin(), val, binOp1, binOp2);
  404. }
  405. template <class T>
  406. constexpr T MinElement(T begin, T end) {
  407. return std::min_element(begin, end);
  408. }
  409. template <class T, class C>
  410. constexpr T MinElement(T begin, T end, C comp) {
  411. return std::min_element(begin, end, comp);
  412. }
  413. template <class T>
  414. constexpr T MaxElement(T begin, T end) {
  415. return std::max_element(begin, end);
  416. }
  417. template <class T, class C>
  418. constexpr T MaxElement(T begin, T end, C comp) {
  419. return std::max_element(begin, end, comp);
  420. }
  421. template <class I, class F>
  422. constexpr I MaxElementBy(I begin, I end, F&& func) {
  423. using TValue = decltype(func(*begin));
  424. return ::NPrivate::ExtremeElementBy(begin, end, std::forward<F>(func), TGreater<TValue>());
  425. }
  426. template <class C, class F>
  427. constexpr auto MaxElementBy(C& c, F&& func) {
  428. return MaxElementBy(std::begin(c), std::end(c), std::forward<F>(func));
  429. }
  430. template <class C, class F>
  431. constexpr auto MaxElementBy(const C& c, F&& func) {
  432. return MaxElementBy(std::begin(c), std::end(c), std::forward<F>(func));
  433. }
  434. template <class I, class F>
  435. constexpr I MinElementBy(I begin, I end, F&& func) {
  436. using TValue = decltype(func(*begin));
  437. return ::NPrivate::ExtremeElementBy(begin, end, std::forward<F>(func), TLess<TValue>());
  438. }
  439. template <class C, class F>
  440. constexpr auto MinElementBy(C& c, F&& func) {
  441. return MinElementBy(std::begin(c), std::end(c), std::forward<F>(func));
  442. }
  443. template <class C, class F>
  444. constexpr auto MinElementBy(const C& c, F&& func) {
  445. return MinElementBy(std::begin(c), std::end(c), std::forward<F>(func));
  446. }
  447. template <class TOp, class... TArgs>
  448. void ApplyToMany(TOp op, TArgs&&... args) {
  449. int dummy[] = {((void)op(std::forward<TArgs>(args)), 0)...};
  450. Y_UNUSED(dummy);
  451. }
  452. template <class TI, class TOp>
  453. constexpr void ForEach(TI f, TI l, TOp op) {
  454. std::for_each(f, l, op);
  455. }
  456. namespace NPrivate {
  457. template <class T, class TOp, size_t... Is>
  458. constexpr bool AllOfImpl(T&& t, TOp&& op, std::index_sequence<Is...>) {
  459. #if _LIBCPP_STD_VER >= 17
  460. return (true && ... && op(std::get<Is>(std::forward<T>(t))));
  461. #else
  462. bool result = true;
  463. auto wrapper = [&result, &op](auto&& x) { result = result && op(std::forward<decltype(x)>(x)); };
  464. int dummy[] = {(wrapper(std::get<Is>(std::forward<T>(t))), 0)...};
  465. Y_UNUSED(dummy);
  466. return result;
  467. #endif
  468. }
  469. template <class T, class TOp, size_t... Is>
  470. constexpr bool AnyOfImpl(T&& t, TOp&& op, std::index_sequence<Is...>) {
  471. #if _LIBCPP_STD_VER >= 17
  472. return (false || ... || op(std::get<Is>(std::forward<T>(t))));
  473. #else
  474. bool result = false;
  475. auto wrapper = [&result, &op](auto&& x) { result = result || op(std::forward<decltype(x)>(x)); };
  476. int dummy[] = {(wrapper(std::get<Is>(std::forward<T>(t))), 0)...};
  477. Y_UNUSED(dummy);
  478. return result;
  479. #endif
  480. }
  481. template <class T, class TOp, size_t... Is>
  482. constexpr void ForEachImpl(T&& t, TOp&& op, std::index_sequence<Is...>) {
  483. #if _LIBCPP_STD_VER >= 17
  484. (..., op(std::get<Is>(std::forward<T>(t))));
  485. #else
  486. ::ApplyToMany(std::forward<TOp>(op), std::get<Is>(std::forward<T>(t))...);
  487. #endif
  488. }
  489. }
  490. // check that TOp return true for all of element from tuple T
  491. template <class T, class TOp>
  492. constexpr ::TEnableIfTuple<T, bool> AllOf(T&& t, TOp&& op) {
  493. return ::NPrivate::AllOfImpl(
  494. std::forward<T>(t),
  495. std::forward<TOp>(op),
  496. std::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>{});
  497. }
  498. // check that TOp return true for at least one element from tuple T
  499. template <class T, class TOp>
  500. constexpr ::TEnableIfTuple<T, bool> AnyOf(T&& t, TOp&& op) {
  501. return ::NPrivate::AnyOfImpl(
  502. std::forward<T>(t),
  503. std::forward<TOp>(op),
  504. std::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>{});
  505. }
  506. template <class T, class TOp>
  507. constexpr ::TEnableIfTuple<T> ForEach(T&& t, TOp&& op) {
  508. ::NPrivate::ForEachImpl(
  509. std::forward<T>(t),
  510. std::forward<TOp>(op),
  511. std::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>{});
  512. }
  513. template <class T1, class T2, class O>
  514. constexpr void Transform(T1 b, T1 e, T2 o, O f) {
  515. std::transform(b, e, o, f);
  516. }
  517. template <class T1, class T2, class T3, class O>
  518. constexpr void Transform(T1 b1, T1 e1, T2 b2, T3 o, O f) {
  519. std::transform(b1, e1, b2, o, f);
  520. }
  521. template <class T, class V>
  522. constexpr typename std::iterator_traits<T>::difference_type Count(T first, T last, const V& value) {
  523. return std::count(first, last, value);
  524. }
  525. template <class TContainer, class TValue>
  526. constexpr auto Count(const TContainer& container, const TValue& value) {
  527. return Count(std::cbegin(container), std::cend(container), value);
  528. }
  529. template <class It, class P>
  530. constexpr auto CountIf(It first, It last, P p) {
  531. return std::count_if(first, last, p);
  532. }
  533. template <class C, class P>
  534. constexpr auto CountIf(const C& c, P pred) {
  535. using std::begin;
  536. using std::end;
  537. return CountIf(begin(c), end(c), pred);
  538. }
  539. template <class I1, class I2>
  540. constexpr std::pair<I1, I2> Mismatch(I1 b1, I1 e1, I2 b2) {
  541. return std::mismatch(b1, e1, b2);
  542. }
  543. template <class I1, class I2, class P>
  544. constexpr std::pair<I1, I2> Mismatch(I1 b1, I1 e1, I2 b2, P p) {
  545. return std::mismatch(b1, e1, b2, p);
  546. }
  547. template <class RandomIterator>
  548. constexpr void NthElement(RandomIterator begin, RandomIterator nth, RandomIterator end) {
  549. std::nth_element(begin, nth, end);
  550. }
  551. template <class RandomIterator, class Compare>
  552. constexpr void NthElement(RandomIterator begin, RandomIterator nth, RandomIterator end, Compare compare) {
  553. std::nth_element(begin, nth, end, compare);
  554. }
  555. // no standard implementation until C++14
  556. template <class I1, class I2>
  557. constexpr std::pair<I1, I2> Mismatch(I1 b1, I1 e1, I2 b2, I2 e2) {
  558. while (b1 != e1 && b2 != e2 && *b1 == *b2) {
  559. ++b1;
  560. ++b2;
  561. }
  562. return std::make_pair(b1, b2);
  563. }
  564. template <class I1, class I2, class P>
  565. constexpr std::pair<I1, I2> Mismatch(I1 b1, I1 e1, I2 b2, I2 e2, P p) {
  566. while (b1 != e1 && b2 != e2 && p(*b1, *b2)) {
  567. ++b1;
  568. ++b2;
  569. }
  570. return std::make_pair(b1, b2);
  571. }
  572. template <class It, class Val>
  573. constexpr bool BinarySearch(It begin, It end, const Val& val) {
  574. return std::binary_search(begin, end, val);
  575. }
  576. template <class It, class Val, class Comp>
  577. constexpr bool BinarySearch(It begin, It end, const Val& val, Comp comp) {
  578. return std::binary_search(begin, end, val, comp);
  579. }
  580. template <class It, class Val>
  581. constexpr std::pair<It, It> EqualRange(It begin, It end, const Val& val) {
  582. return std::equal_range(begin, end, val);
  583. }
  584. template <class It, class Val, class Comp>
  585. constexpr std::pair<It, It> EqualRange(It begin, It end, const Val& val, Comp comp) {
  586. return std::equal_range(begin, end, val, comp);
  587. }
  588. template <class TContainer>
  589. constexpr auto AdjacentFind(TContainer&& c) {
  590. using std::begin;
  591. using std::end;
  592. return std::adjacent_find(begin(c), end(c));
  593. }
  594. template <class TContainer, class Compare>
  595. constexpr auto AdjacentFind(TContainer&& c, Compare comp) {
  596. using std::begin;
  597. using std::end;
  598. return std::adjacent_find(begin(c), end(c), comp);
  599. }
  600. namespace NPrivate {
  601. template <class TForwardIterator, class TGetKey>
  602. constexpr TForwardIterator AdjacentFindBy(TForwardIterator begin, TForwardIterator end, const TGetKey& getKey) {
  603. return std::adjacent_find(begin, end, [&](auto&& left, auto&& right) { return getKey(left) == getKey(right); });
  604. }
  605. }
  606. template <class TContainer, class TGetKey>
  607. constexpr auto AdjacentFindBy(TContainer&& c, const TGetKey& getKey) {
  608. using std::begin;
  609. using std::end;
  610. return ::NPrivate::AdjacentFindBy(begin(c), end(c), getKey);
  611. }
  612. template <class ForwardIt>
  613. constexpr bool IsSorted(ForwardIt begin, ForwardIt end) {
  614. return std::is_sorted(begin, end);
  615. }
  616. template <class ForwardIt, class Compare>
  617. constexpr bool IsSorted(ForwardIt begin, ForwardIt end, Compare comp) {
  618. return std::is_sorted(begin, end, comp);
  619. }
  620. template <class TIterator, typename TGetKey>
  621. constexpr bool IsSortedBy(TIterator begin, TIterator end, const TGetKey& getKey) {
  622. return IsSorted(begin, end, [&](auto&& left, auto&& right) { return getKey(left) < getKey(right); });
  623. }
  624. template <class TContainer, typename TGetKey>
  625. constexpr bool IsSortedBy(const TContainer& c, const TGetKey& getKey) {
  626. using std::begin;
  627. using std::end;
  628. return IsSortedBy(begin(c), end(c), getKey);
  629. }
  630. template <class It, class Val>
  631. constexpr void Iota(It begin, It end, Val val) {
  632. std::iota(begin, end, val);
  633. }
  634. template <class TI, class TO, class S>
  635. constexpr TO CopyN(TI from, S s, TO to) {
  636. return std::copy_n(from, s, to);
  637. }
  638. template <class TI, class TO, class P>
  639. constexpr TO CopyIf(TI begin, TI end, TO to, P pred) {
  640. return std::copy_if(begin, end, to, pred);
  641. }
  642. template <class T>
  643. constexpr std::pair<const T&, const T&> MinMax(const T& first, const T& second) {
  644. return std::minmax(first, second);
  645. }
  646. template <class It>
  647. constexpr std::pair<It, It> MinMaxElement(It first, It last) {
  648. return std::minmax_element(first, last);
  649. }
  650. template <class TIterator, class TGenerator>
  651. constexpr void Generate(TIterator first, TIterator last, TGenerator generator) {
  652. std::generate(first, last, generator);
  653. }
  654. template <class TIterator, class TSize, class TGenerator>
  655. constexpr void GenerateN(TIterator first, TSize count, TGenerator generator) {
  656. std::generate_n(first, count, generator);
  657. }