algorithm_ut.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. #include <library/cpp/testing/unittest/registar.h>
  2. #include "algorithm.h"
  3. #include "hash.h"
  4. #include "hash_multi_map.h"
  5. #include "strbuf.h"
  6. #include "string.h"
  7. static auto isOne = [](char c) { return c == '1'; };
  8. Y_UNIT_TEST_SUITE(TAlgorithm) {
  9. Y_UNIT_TEST(AnyTest) {
  10. UNIT_ASSERT(0 == AnyOf(TStringBuf("00"), isOne));
  11. UNIT_ASSERT(1 == AnyOf(TStringBuf("01"), isOne));
  12. UNIT_ASSERT(1 == AnyOf(TStringBuf("10"), isOne));
  13. UNIT_ASSERT(1 == AnyOf(TStringBuf("11"), isOne));
  14. UNIT_ASSERT(0 == AnyOf(TStringBuf(), isOne));
  15. const char array00[]{'0', '0'};
  16. UNIT_ASSERT(0 == AnyOf(array00, isOne));
  17. const char array01[]{'0', '1'};
  18. UNIT_ASSERT(1 == AnyOf(array01, isOne));
  19. }
  20. Y_UNIT_TEST(AllOfTest) {
  21. UNIT_ASSERT(0 == AllOf(TStringBuf("00"), isOne));
  22. UNIT_ASSERT(0 == AllOf(TStringBuf("01"), isOne));
  23. UNIT_ASSERT(0 == AllOf(TStringBuf("10"), isOne));
  24. UNIT_ASSERT(1 == AllOf(TStringBuf("11"), isOne));
  25. UNIT_ASSERT(1 == AllOf(TStringBuf(), isOne));
  26. const char array01[]{'0', '1'};
  27. UNIT_ASSERT(0 == AllOf(array01, isOne));
  28. const char array11[]{'1', '1'};
  29. UNIT_ASSERT(1 == AllOf(array11, isOne));
  30. }
  31. Y_UNIT_TEST(CountIfTest) {
  32. UNIT_ASSERT(3 == CountIf(TStringBuf("____1________1____1_______"), isOne));
  33. UNIT_ASSERT(5 == CountIf(TStringBuf("1____1________1____1_______1"), isOne));
  34. UNIT_ASSERT(0 == CountIf(TStringBuf("___________"), isOne));
  35. UNIT_ASSERT(0 == CountIf(TStringBuf(), isOne));
  36. UNIT_ASSERT(1 == CountIf(TStringBuf("1"), isOne));
  37. const char array[] = "____1________1____1_______";
  38. UNIT_ASSERT(3 == CountIf(array, isOne));
  39. }
  40. Y_UNIT_TEST(CountTest) {
  41. UNIT_ASSERT(3 == Count("____1________1____1_______", '1'));
  42. UNIT_ASSERT(3 == Count(TStringBuf("____1________1____1_______"), '1'));
  43. UNIT_ASSERT(5 == Count(TStringBuf("1____1________1____1_______1"), '1'));
  44. UNIT_ASSERT(0 == Count(TStringBuf("___________"), '1'));
  45. UNIT_ASSERT(0 == Count(TStringBuf(), '1'));
  46. UNIT_ASSERT(1 == Count(TStringBuf("1"), '1'));
  47. const char array[] = "____1________1____1_______";
  48. UNIT_ASSERT(3 == Count(array, '1'));
  49. }
  50. struct TStrokaNoCopy: TString {
  51. public:
  52. TStrokaNoCopy(const char* p)
  53. : TString(p)
  54. {
  55. }
  56. private:
  57. TStrokaNoCopy(const TStrokaNoCopy&);
  58. void operator=(const TStrokaNoCopy&);
  59. };
  60. Y_UNIT_TEST(CountOfTest) {
  61. UNIT_ASSERT_VALUES_EQUAL(CountOf(1, 2), 0);
  62. UNIT_ASSERT_VALUES_EQUAL(CountOf(1, 1), 1);
  63. UNIT_ASSERT_VALUES_EQUAL(CountOf(2, 4, 5), 0);
  64. UNIT_ASSERT_VALUES_EQUAL(CountOf(2, 4, 2), 1);
  65. UNIT_ASSERT_VALUES_EQUAL(CountOf(3, 3, 3), 2);
  66. // Checking comparison of different types.
  67. UNIT_ASSERT_VALUES_EQUAL(CountOf(0x61, 'x', 'y', 'z'), 0);
  68. UNIT_ASSERT_VALUES_EQUAL(CountOf(0x61, 'a', 'b', 'c', 0x61), 2);
  69. UNIT_ASSERT_VALUES_EQUAL(CountOf(0x61, 'a', 'b', 'c', 0x61ll), 2);
  70. // TString and const char *
  71. UNIT_ASSERT_VALUES_EQUAL(CountOf(TString("xyz"), "123", "poi"), 0);
  72. UNIT_ASSERT_VALUES_EQUAL(CountOf(TString("xyz"), "123", "poi", "xyz"), 1);
  73. // TString and TStringBuf
  74. UNIT_ASSERT_VALUES_EQUAL(CountOf(TString("xyz"), TStringBuf("123"), TStringBuf("poi")), 0);
  75. UNIT_ASSERT_VALUES_EQUAL(CountOf(TString("xyz"), TStringBuf("123"), TStringBuf("poi"),
  76. TStringBuf("xyz")),
  77. 1);
  78. // TStringBuf and const char *
  79. UNIT_ASSERT_VALUES_EQUAL(CountOf(TStringBuf("xyz"), "123", "poi"), 0);
  80. UNIT_ASSERT_VALUES_EQUAL(CountOf(TStringBuf("xyz"), "123", "poi", "xyz"), 1);
  81. // TStringBuf and TString
  82. UNIT_ASSERT_VALUES_EQUAL(CountOf(TStringBuf("xyz"), TString("123"), TString("poi")), 0);
  83. UNIT_ASSERT_VALUES_EQUAL(CountOf(TStringBuf("xyz"), TString("123"), TString("poi"),
  84. TString("xyz")),
  85. 1);
  86. }
  87. Y_UNIT_TEST(EqualToOneOfTest) {
  88. UNIT_ASSERT(1 == EqualToOneOf(1, 1, 2));
  89. UNIT_ASSERT(1 == EqualToOneOf(2, 1, 2));
  90. UNIT_ASSERT(0 == EqualToOneOf(3, 1, 2));
  91. UNIT_ASSERT(1 == EqualToOneOf(1, 1));
  92. UNIT_ASSERT(0 == EqualToOneOf(1, 2));
  93. UNIT_ASSERT(0 == EqualToOneOf(3));
  94. //test, that EqualToOneOf can compare different types, and don't copy objects:
  95. TStrokaNoCopy x("x");
  96. TStrokaNoCopy y("y");
  97. TStrokaNoCopy z("z");
  98. const char* px = "x";
  99. const char* py = "y";
  100. const char* pz = "z";
  101. UNIT_ASSERT(1 == EqualToOneOf(x, px, py));
  102. UNIT_ASSERT(1 == EqualToOneOf(y, px, py));
  103. UNIT_ASSERT(1 == EqualToOneOf(y, px, y));
  104. UNIT_ASSERT(1 == EqualToOneOf(y, x, py));
  105. UNIT_ASSERT(0 == EqualToOneOf(z, px, py));
  106. UNIT_ASSERT(1 == EqualToOneOf(px, x, y));
  107. UNIT_ASSERT(1 == EqualToOneOf(py, x, y));
  108. UNIT_ASSERT(0 == EqualToOneOf(pz, x, y));
  109. }
  110. template <class TTestConstPtr>
  111. void TestFindPtrFoundValue(int j, TTestConstPtr root) {
  112. if (j == 3) {
  113. UNIT_ASSERT(root && *root == 3);
  114. } else if (j == 4) {
  115. UNIT_ASSERT(root == nullptr);
  116. } else {
  117. ythrow yexception() << "invalid param " << j;
  118. }
  119. }
  120. template <class TTestConstPtr>
  121. void TestFindIfPtrFoundValue(int j, TTestConstPtr root) {
  122. if (j == 3) {
  123. UNIT_ASSERT(root == nullptr);
  124. } else if (j == 4) {
  125. UNIT_ASSERT(root && *root == 2);
  126. } else {
  127. ythrow yexception() << "invalid param " << j;
  128. }
  129. }
  130. struct TVectorNoCopy: std::vector<int> {
  131. public:
  132. TVectorNoCopy() = default;
  133. private:
  134. TVectorNoCopy(const TVectorNoCopy&);
  135. void operator=(const TVectorNoCopy&);
  136. };
  137. Y_UNIT_TEST(FindPtrTest) {
  138. TVectorNoCopy v;
  139. v.push_back(1);
  140. v.push_back(2);
  141. v.push_back(3);
  142. int array[3] = {1, 2, 3};
  143. const int array_const[3] = {1, 2, 3};
  144. //test (const, non-const) * (iterator, vector, array) * (found, not found) variants.
  145. // value '3' is in container, value '4' is not
  146. for (int j = 3; j <= 4; ++j) {
  147. TestFindPtrFoundValue<int*>(j, FindPtr(v, j));
  148. TestFindPtrFoundValue<int*>(j, FindPtr(v.begin(), v.end(), j));
  149. const TVectorNoCopy& q = v;
  150. TestFindPtrFoundValue<const int*>(j, FindPtr(q, j));
  151. TestFindPtrFoundValue<const int*>(j, FindPtr(q.begin(), q.end(), j));
  152. TestFindPtrFoundValue<int*>(j, FindPtr(array, j));
  153. TestFindPtrFoundValue<const int*>(j, FindPtr(array_const, j));
  154. }
  155. }
  156. Y_UNIT_TEST(FindIfPtrTest) {
  157. TVectorNoCopy v;
  158. v.push_back(1);
  159. v.push_back(2);
  160. v.push_back(3);
  161. int array[3] = {1, 2, 3};
  162. const int array_const[3] = {1, 2, 3};
  163. //test (const, non-const) * (iterator, vector, array) * (found, not found) variants.
  164. // search, that 2*2 == 4, but there is no value 'x' in array that (x*x == 3)
  165. for (int j = 3; j <= 4; ++j) {
  166. TestFindIfPtrFoundValue<int*>(j, FindIfPtr(v, [j](int i) { return i * i == j; }));
  167. TestFindIfPtrFoundValue<int*>(j, FindIfPtr(v.begin(), v.end(), [j](int i) { return i * i == j; }));
  168. const TVectorNoCopy& q = v;
  169. TestFindIfPtrFoundValue<const int*>(j, FindIfPtr(q, [j](int i) { return i * i == j; }));
  170. TestFindIfPtrFoundValue<const int*>(j, FindIfPtr(q.begin(), q.end(), [j](int i) { return i * i == j; }));
  171. TestFindIfPtrFoundValue<int*>(j, FindIfPtr(array, [j](int i) { return i * i == j; }));
  172. TestFindIfPtrFoundValue<const int*>(j, FindIfPtr(array_const, [j](int i) { return i * i == j; }));
  173. }
  174. }
  175. Y_UNIT_TEST(FindIndexTest) {
  176. TVectorNoCopy v;
  177. v.push_back(1);
  178. v.push_back(2);
  179. v.push_back(3);
  180. UNIT_ASSERT_EQUAL(0, FindIndex(v, 1));
  181. UNIT_ASSERT_EQUAL(1, FindIndex(v, 2));
  182. UNIT_ASSERT_EQUAL(2, FindIndex(v, 3));
  183. UNIT_ASSERT_EQUAL(NPOS, FindIndex(v, 42));
  184. int array[3] = {1, 2, 3};
  185. UNIT_ASSERT_EQUAL(0, FindIndex(array, 1));
  186. UNIT_ASSERT_EQUAL(1, FindIndex(array, 2));
  187. UNIT_ASSERT_EQUAL(2, FindIndex(array, 3));
  188. UNIT_ASSERT_EQUAL(NPOS, FindIndex(array, 42));
  189. TVector<int> empty;
  190. UNIT_ASSERT_EQUAL(NPOS, FindIndex(empty, 0));
  191. }
  192. Y_UNIT_TEST(FindIndexIfTest) {
  193. TVectorNoCopy v;
  194. v.push_back(1);
  195. v.push_back(2);
  196. v.push_back(3);
  197. UNIT_ASSERT_EQUAL(0, FindIndexIf(v, [](int x) { return x == 1; }));
  198. UNIT_ASSERT_EQUAL(1, FindIndexIf(v, [](int x) { return x == 2; }));
  199. UNIT_ASSERT_EQUAL(2, FindIndexIf(v, [](int x) { return x == 3; }));
  200. UNIT_ASSERT_EQUAL(NPOS, FindIndexIf(v, [](int x) { return x == 42; }));
  201. int array[3] = {1, 2, 3};
  202. UNIT_ASSERT_EQUAL(0, FindIndexIf(array, [](int x) { return x == 1; }));
  203. UNIT_ASSERT_EQUAL(1, FindIndexIf(array, [](int x) { return x == 2; }));
  204. UNIT_ASSERT_EQUAL(2, FindIndexIf(array, [](int x) { return x == 3; }));
  205. UNIT_ASSERT_EQUAL(NPOS, FindIndexIf(array, [](int x) { return x == 42; }));
  206. TVector<int> empty;
  207. UNIT_ASSERT_EQUAL(NPOS, FindIndexIf(empty, [](int x) { return x == 3; }));
  208. }
  209. Y_UNIT_TEST(SortUniqueTest) {
  210. {
  211. TVector<TString> v;
  212. SortUnique(v);
  213. UNIT_ASSERT_EQUAL(v, TVector<TString>());
  214. }
  215. {
  216. const char* ar[] = {"345", "3", "123", "2", "23", "3", "2"};
  217. TVector<TString> v(ar, ar + Y_ARRAY_SIZE(ar));
  218. SortUnique(v);
  219. const char* suAr[] = {"123", "2", "23", "3", "345"};
  220. TVector<TString> suV(suAr, suAr + Y_ARRAY_SIZE(suAr));
  221. UNIT_ASSERT_EQUAL(v, suV);
  222. }
  223. }
  224. Y_UNIT_TEST(EraseTest) {
  225. TVector<int> data = {5, 4, 3, 2, 1, 0};
  226. TVector<int> expected = {5, 4, 2, 1, 0};
  227. Erase(data, 3);
  228. UNIT_ASSERT_EQUAL(data, expected);
  229. }
  230. Y_UNIT_TEST(EraseIfTest) {
  231. TVector<int> data = {5, 4, 3, 2, 1, 0};
  232. TVector<int> expected = {2, 1, 0};
  233. EraseIf(data, [](int i) { return i >= 3; });
  234. UNIT_ASSERT_EQUAL(data, expected);
  235. }
  236. Y_UNIT_TEST(EraseNodesIfTest) {
  237. TMap<int, int> map{{1, 1}, {2, 2}, {3, 5}};
  238. TMap<int, int> expectedMap{{1, 1}};
  239. EraseNodesIf(map, [](auto p) { return p.first >= 2; });
  240. UNIT_ASSERT_EQUAL(map, expectedMap);
  241. TMultiMap<int, int> multiMap{{1, 1}, {1, 3}, {2, 2}, {3, 5}};
  242. TMultiMap<int, int> expectedMultiMap{{1, 1}, {1, 3}};
  243. EraseNodesIf(multiMap, [](auto p) { return p.first >= 2; });
  244. UNIT_ASSERT_EQUAL(multiMap, expectedMultiMap);
  245. TSet<int> set{1, 2, 3, 4, 5, 6, 7};
  246. TSet<int> expectedSet{1, 3, 5, 7};
  247. EraseNodesIf(set, [](int i) { return i % 2 == 0; });
  248. UNIT_ASSERT_EQUAL(set, expectedSet);
  249. TMultiSet<int> multiSet{1, 1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 7};
  250. TMultiSet<int> expectedMultiSet{1, 1, 3, 5, 5, 5, 7};
  251. EraseNodesIf(multiSet, [](int i) { return i % 2 == 0; });
  252. UNIT_ASSERT_EQUAL(multiSet, expectedMultiSet);
  253. THashMap<int, int> hashMap{{1, 0}, {3, 0}, {4, 0}, {10, 0}, {2, 0}, {5, 2}};
  254. THashMap<int, int> expectedHashMap{{1, 0}, {3, 0}, {5, 2}};
  255. EraseNodesIf(hashMap, [](auto p) { return p.first % 2 == 0; });
  256. UNIT_ASSERT_EQUAL(hashMap, expectedHashMap);
  257. THashMultiMap<int, int> hashMultiMap{{1, 0}, {3, 0}, {4, 0}, {10, 0}, {2, 0}, {5, 0}, {1, 0}, {1, 0}, {2, 0}, {2, 2}};
  258. THashMultiMap<int, int> expectedHashMultiMap{{1, 0}, {1, 0}, {1, 0}, {3, 0}, {5, 0}};
  259. EraseNodesIf(hashMultiMap, [](auto p) { return p.first % 2 == 0; });
  260. UNIT_ASSERT_EQUAL(hashMultiMap, expectedHashMultiMap);
  261. }
  262. Y_UNIT_TEST(NthElementTest) {
  263. {
  264. TVector<TString> v;
  265. NthElement(v.begin(), v.begin(), v.end());
  266. UNIT_ASSERT_EQUAL(v, TVector<TString>());
  267. }
  268. {
  269. int data[] = {3, 2, 1, 4, 6, 5, 7, 9, 8};
  270. TVector<int> testVector(data, data + Y_ARRAY_SIZE(data));
  271. size_t medianInd = testVector.size() / 2;
  272. NthElement(testVector.begin(), testVector.begin() + medianInd, testVector.end());
  273. UNIT_ASSERT_EQUAL(testVector[medianInd], 5);
  274. NthElement(testVector.begin(), testVector.begin() + medianInd, testVector.end(), [](int lhs, int rhs) { return lhs > rhs; });
  275. UNIT_ASSERT_EQUAL(testVector[medianInd], 5);
  276. }
  277. {
  278. const char* data[] = {"3", "234", "1231", "333", "545345", "11", "111", "55", "66"};
  279. TVector<TString> testVector(data, data + Y_ARRAY_SIZE(data));
  280. size_t medianInd = testVector.size() / 2;
  281. NthElement(testVector.begin(), testVector.begin() + medianInd, testVector.end());
  282. auto median = testVector.begin() + medianInd;
  283. for (auto it0 = testVector.begin(); it0 != median; ++it0) {
  284. for (auto it1 = median; it1 != testVector.end(); ++it1) {
  285. UNIT_ASSERT(*it0 <= *it1);
  286. }
  287. }
  288. }
  289. }
  290. Y_UNIT_TEST(BinarySearchTest) {
  291. {
  292. TVector<TString> v;
  293. bool test = BinarySearch(v.begin(), v.end(), "test");
  294. UNIT_ASSERT_EQUAL(test, false);
  295. }
  296. {
  297. int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  298. bool test = BinarySearch(data, data + Y_ARRAY_SIZE(data), 2);
  299. UNIT_ASSERT_EQUAL(test, true);
  300. test = BinarySearch(data, data + Y_ARRAY_SIZE(data), 10);
  301. UNIT_ASSERT_EQUAL(test, false);
  302. }
  303. {
  304. TVector<size_t> data = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
  305. bool test = BinarySearch(data.begin(), data.end(), (size_t)9, TGreater<size_t>());
  306. UNIT_ASSERT_EQUAL(test, true);
  307. test = BinarySearch(data.begin(), data.end(), (size_t)11, TGreater<size_t>());
  308. UNIT_ASSERT_EQUAL(test, false);
  309. test = BinarySearch(data.rbegin(), data.rend(), (size_t)1);
  310. UNIT_ASSERT_EQUAL(test, true);
  311. }
  312. }
  313. Y_UNIT_TEST(EqualRangeTest) {
  314. {
  315. TVector<TString> v;
  316. using PairOfVector = std::pair<TVector<TString>::iterator, TVector<TString>::iterator>;
  317. PairOfVector tmp = EqualRange(v.begin(), v.end(), "tmp");
  318. UNIT_ASSERT_EQUAL(tmp.first, tmp.second);
  319. UNIT_ASSERT_EQUAL(tmp.first, v.end());
  320. }
  321. {
  322. int data[] = {1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5};
  323. using PairOfInt = std::pair<int*, int*>;
  324. PairOfInt tmp = EqualRange(data, data + Y_ARRAY_SIZE(data), 3);
  325. UNIT_ASSERT_EQUAL(tmp.second - tmp.first, 4);
  326. UNIT_ASSERT_EQUAL(tmp.first - data, 7);
  327. UNIT_ASSERT_EQUAL(data + Y_ARRAY_SIZE(data) - tmp.second, 2);
  328. }
  329. {
  330. TVector<size_t> data = {9, 9, 8, 8, 8, 5, 4, 3, 3, 0, 0};
  331. using PairOfVector = std::pair<TVector<size_t>::iterator, TVector<size_t>::iterator>;
  332. PairOfVector tmp = EqualRange(data.begin(), data.end(), 8, TGreater<size_t>());
  333. UNIT_ASSERT_EQUAL(tmp.first - data.begin(), 2);
  334. UNIT_ASSERT_EQUAL(tmp.second - tmp.first, 3);
  335. using PairOfVectorReverse = std::pair<TVector<size_t>::reverse_iterator, TVector<size_t>::reverse_iterator>;
  336. PairOfVectorReverse tmpR = EqualRange(data.rbegin(), data.rend(), (size_t)0);
  337. UNIT_ASSERT_EQUAL(tmpR.first, data.rbegin());
  338. UNIT_ASSERT_EQUAL(tmpR.second - tmpR.first, 2);
  339. }
  340. }
  341. Y_UNIT_TEST(AdjacentFindTest) {
  342. TVector<int> v0;
  343. UNIT_ASSERT_EQUAL(AdjacentFind(v0), v0.end());
  344. TVector<int> v1 = {1};
  345. UNIT_ASSERT_EQUAL(AdjacentFind(v1), v1.end());
  346. const int v2[] = {8, 7, 6, 6, 5, 5, 5, 4, 3, 2, 1};
  347. UNIT_ASSERT_EQUAL(AdjacentFind(v2), std::begin(v2) + 2);
  348. TVector<TStringBuf> v3 = {"six", "five", "four", "three", "two", "one"};
  349. UNIT_ASSERT_EQUAL(AdjacentFind(v3), v3.end());
  350. TVector<int> v4 = {1, 1, 1, 1, 1};
  351. for (;;) {
  352. if (auto it = AdjacentFind(v4); it == v4.end()) {
  353. break;
  354. } else {
  355. *it += 1;
  356. }
  357. }
  358. UNIT_ASSERT_VALUES_EQUAL(v4, (TVector<int>{5, 4, 3, 2, 1}));
  359. }
  360. Y_UNIT_TEST(AdjacentFindByTest) {
  361. TVector<int> v0;
  362. UNIT_ASSERT_EQUAL(AdjacentFindBy(v0, std::negate<int>()), v0.end());
  363. TVector<int> v1 = {1};
  364. UNIT_ASSERT_EQUAL(AdjacentFindBy(v1, std::negate<int>()), v1.end());
  365. const int v2[] = {8, 7, 6, 6, 5, 5, 5, 4, 3, 2, 1};
  366. UNIT_ASSERT_EQUAL(AdjacentFindBy(v2, std::negate<int>()), std::begin(v2) + 2);
  367. UNIT_ASSERT_EQUAL(AdjacentFindBy(v2, [](const auto& e) { return e / 8; }), std::begin(v2) + 1);
  368. TVector<TStringBuf> v3 = {"six", "five", "four", "three", "two", "one"};
  369. UNIT_ASSERT_EQUAL(AdjacentFind(v3), v3.end());
  370. UNIT_ASSERT_EQUAL(AdjacentFindBy(v3, std::mem_fn(&TStringBuf::size)), v3.begin() + 1);
  371. TVector<int> v4 = {101, 201, 301, 401, 501};
  372. for (;;) {
  373. if (auto it = AdjacentFindBy(v4, [](int a) { return a % 10; }); it == v4.end()) {
  374. break;
  375. } else {
  376. *it += 1;
  377. }
  378. }
  379. UNIT_ASSERT_VALUES_EQUAL(v4, (TVector<int>{105, 204, 303, 402, 501}));
  380. }
  381. Y_UNIT_TEST(IsSortedTest) {
  382. TVector<int> v0;
  383. UNIT_ASSERT_VALUES_EQUAL(IsSorted(v0.begin(), v0.end()), true);
  384. TVector<int> v1 = {1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8};
  385. UNIT_ASSERT_VALUES_EQUAL(IsSorted(v1.begin(), v1.end()), true);
  386. UNIT_ASSERT_VALUES_EQUAL(IsSorted(v1.begin(), v1.end(), TLess<int>()), true);
  387. UNIT_ASSERT_VALUES_EQUAL(IsSorted(v1.begin(), v1.end(), TGreater<int>()), false);
  388. TVector<int> v2 = {1, 2, 1};
  389. UNIT_ASSERT_VALUES_EQUAL(IsSorted(v2.begin(), v2.end()), false);
  390. UNIT_ASSERT_VALUES_EQUAL(IsSorted(v2.begin(), v2.end(), TLess<int>()), false);
  391. UNIT_ASSERT_VALUES_EQUAL(IsSorted(v2.begin(), v2.end(), TGreater<int>()), false);
  392. }
  393. Y_UNIT_TEST(IsSortedByTest) {
  394. TVector<int> v0;
  395. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v0.begin(), v0.end(), std::negate<int>()), true);
  396. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v0, std::negate<int>()), true);
  397. TVector<int> v1 = {1};
  398. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v1.begin(), v1.end(), std::negate<int>()), true);
  399. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v1, std::negate<int>()), true);
  400. TVector<int> v2 = {8, 7, 6, 6, 5, 5, 5, 4, 3, 2, 1};
  401. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v2.begin(), v2.end(), std::negate<int>()), true);
  402. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v2, std::negate<int>()), true);
  403. TVector<int> v3 = {1, 2, 1};
  404. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v3.begin(), v3.end(), std::negate<int>()), false);
  405. UNIT_ASSERT_VALUES_EQUAL(IsSortedBy(v3, std::negate<int>()), false);
  406. }
  407. Y_UNIT_TEST(SortTestTwoIterators) {
  408. TVector<int> collection = {10, 2, 7};
  409. Sort(collection.begin(), collection.end());
  410. TVector<int> expected = {2, 7, 10};
  411. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  412. }
  413. Y_UNIT_TEST(SortTestTwoIteratorsAndComparator) {
  414. TVector<int> collection = {10, 2, 7};
  415. Sort(collection.begin(), collection.end(), [](int l, int r) { return l > r; });
  416. TVector<int> expected = {10, 7, 2};
  417. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  418. }
  419. Y_UNIT_TEST(SortTestContainer) {
  420. TVector<int> collection = {10, 2, 7};
  421. Sort(collection);
  422. TVector<int> expected = {2, 7, 10};
  423. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  424. }
  425. Y_UNIT_TEST(SortTestContainerAndComparator) {
  426. TVector<int> collection = {10, 2, 7};
  427. Sort(collection, [](int l, int r) { return l > r; });
  428. TVector<int> expected = {10, 7, 2};
  429. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  430. }
  431. Y_UNIT_TEST(StableSortTestTwoIterators) {
  432. TVector<int> collection = {10, 2, 7};
  433. StableSort(collection.begin(), collection.end());
  434. TVector<int> expected = {2, 7, 10};
  435. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  436. }
  437. Y_UNIT_TEST(StableSortTestTwoIteratorsAndComparator) {
  438. TVector<int> collection = {404, 101, 106, 203, 102, 205, 401};
  439. StableSort(collection.begin(), collection.end(), [](int l, int r) { return (l / 100) < (r / 100); });
  440. TVector<int> expected = {101, 106, 102, 203, 205, 404, 401};
  441. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  442. }
  443. Y_UNIT_TEST(StableSortTestContainer) {
  444. TVector<int> collection = {10, 2, 7};
  445. StableSort(collection);
  446. TVector<int> expected = {2, 7, 10};
  447. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  448. }
  449. Y_UNIT_TEST(StableSortTestContainerAndComparator) {
  450. TVector<int> collection = {404, 101, 106, 203, 102, 205, 401};
  451. StableSort(collection, [](int l, int r) { return (l / 100) < (r / 100); });
  452. TVector<int> expected = {101, 106, 102, 203, 205, 404, 401};
  453. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  454. }
  455. Y_UNIT_TEST(SortByTest) {
  456. TVector<int> collection = {10, 2, 7};
  457. SortBy(collection, [](int x) { return -x; });
  458. TVector<int> expected = {10, 7, 2};
  459. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  460. }
  461. Y_UNIT_TEST(StableSortByTest) {
  462. TVector<int> collection = {404, 101, 106, 203, 102, 205, 401};
  463. StableSortBy(collection, [](int x) { return x / 100; });
  464. TVector<int> expected = {101, 106, 102, 203, 205, 404, 401};
  465. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  466. }
  467. Y_UNIT_TEST(SortUniqueByTest) {
  468. TVector<int> collection = {404, 101, 101, 203, 101, 203, 404};
  469. StableSortUniqueBy(collection, [](int x) { return x / 100; });
  470. TVector<int> expected = {101, 203, 404};
  471. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  472. }
  473. Y_UNIT_TEST(StableSortUniqueByTest) {
  474. TVector<int> collection = {404, 101, 106, 203, 102, 205, 401};
  475. StableSortUniqueBy(collection, [](int x) { return x / 100; });
  476. TVector<int> expected = {101, 203, 404};
  477. UNIT_ASSERT_VALUES_EQUAL(collection, expected);
  478. }
  479. Y_UNIT_TEST(IotaTest) {
  480. TVector<int> v(10);
  481. Iota(v.begin(), v.end(), 0);
  482. UNIT_ASSERT_VALUES_EQUAL(v[0], 0);
  483. UNIT_ASSERT_VALUES_EQUAL(v[5], 5);
  484. UNIT_ASSERT_VALUES_EQUAL(v[9], 9);
  485. Iota(v.begin() + 2, v.begin() + 5, 162);
  486. UNIT_ASSERT_VALUES_EQUAL(v[0], 0);
  487. UNIT_ASSERT_VALUES_EQUAL(v[3], 163);
  488. UNIT_ASSERT_VALUES_EQUAL(v[9], 9);
  489. }
  490. Y_UNIT_TEST(CopyNTest) {
  491. int data[] = {1, 2, 3, 4, 8, 7, 6, 5};
  492. const size_t vSize = 10;
  493. TVector<int> result(10, 0);
  494. size_t toCopy = 5;
  495. TVector<int>::iterator iter = CopyN(data, toCopy, result.begin());
  496. UNIT_ASSERT_VALUES_EQUAL(iter - result.begin(), toCopy);
  497. UNIT_ASSERT_VALUES_EQUAL(result.size(), 10);
  498. for (size_t idx = 0; idx < toCopy; ++idx) {
  499. UNIT_ASSERT_VALUES_EQUAL(data[idx], result[idx]);
  500. }
  501. for (size_t idx = toCopy; idx < vSize; ++idx) {
  502. UNIT_ASSERT_VALUES_EQUAL(result[idx], 0);
  503. }
  504. toCopy = 8;
  505. const size_t start = 1;
  506. result.assign(vSize, 0);
  507. iter = CopyN(data, toCopy, result.begin() + start);
  508. UNIT_ASSERT_VALUES_EQUAL(iter - result.begin(), start + toCopy);
  509. for (size_t idx = 0; idx < start; ++idx) {
  510. UNIT_ASSERT_VALUES_EQUAL(result[idx], 0);
  511. }
  512. for (size_t idx = 0; idx < toCopy; ++idx) {
  513. UNIT_ASSERT_VALUES_EQUAL(result[start + idx], data[idx]);
  514. }
  515. for (size_t idx = start + toCopy; idx < vSize; ++idx) {
  516. UNIT_ASSERT_VALUES_EQUAL(result[idx], 0);
  517. }
  518. }
  519. Y_UNIT_TEST(CopyIfTest) {
  520. const size_t count = 9;
  521. int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  522. const size_t vSize = 10;
  523. TVector<int> v(vSize, 0);
  524. TVector<int>::iterator iter = CopyIf(data, data + count, v.begin(), [](int x) { return !(x % 3); });
  525. UNIT_ASSERT_VALUES_EQUAL(v.size(), vSize);
  526. UNIT_ASSERT_VALUES_EQUAL(iter - v.begin(), 3);
  527. v.resize(iter - v.begin());
  528. for (size_t idx = 0; idx < v.size(); ++idx) {
  529. UNIT_ASSERT_VALUES_EQUAL(v[idx], 3 * (idx + 1));
  530. }
  531. }
  532. Y_UNIT_TEST(MinMaxElementTest) {
  533. TVector<int> v(10);
  534. Iota(v.begin(), v.end(), 0);
  535. UNIT_ASSERT_EQUAL(*MinMaxElement(v.begin(), v.end()).first, 0);
  536. UNIT_ASSERT_EQUAL(*MinMaxElement(v.begin(), v.end()).second, 9);
  537. v[3] = -2;
  538. v[7] = 11;
  539. UNIT_ASSERT_EQUAL(*MinMaxElement(v.begin(), v.end()).first, -2);
  540. UNIT_ASSERT_EQUAL(*MinMaxElement(v.begin(), v.end()).second, 11);
  541. }
  542. Y_UNIT_TEST(MinMaxTest) {
  543. std::pair<int, int> p1 = MinMax(5, 12);
  544. UNIT_ASSERT_EQUAL(p1.first, 5);
  545. UNIT_ASSERT_EQUAL(p1.second, 12);
  546. std::pair<TString, TString> p2 = MinMax(TString("test"), TString("data"));
  547. UNIT_ASSERT_EQUAL(p2.first, TString("data"));
  548. UNIT_ASSERT_EQUAL(p2.second, TString("test"));
  549. }
  550. Y_UNIT_TEST(TestMaxElementBy) {
  551. const int array[] = {1, 2, 5, 3, 4, 5};
  552. UNIT_ASSERT_VALUES_EQUAL(*MaxElementBy(array, [](int x) {
  553. return x * x;
  554. }), 5);
  555. const TVector<int> vec(array, array + Y_ARRAY_SIZE(array));
  556. UNIT_ASSERT_VALUES_EQUAL(*MaxElementBy(vec, [](int x) {
  557. return -1.0 * x;
  558. }), 1);
  559. int arrayMutable[] = {1, 2, 5, 3, 4, 5};
  560. auto maxPtr = MaxElementBy(arrayMutable, [](int x) { return x; });
  561. *maxPtr += 100;
  562. UNIT_ASSERT_VALUES_EQUAL(*maxPtr, 105);
  563. auto identity = [](char x) {
  564. return x;
  565. };
  566. auto singleElementSequence = {'z'};
  567. UNIT_ASSERT_VALUES_EQUAL(*MaxElementBy(singleElementSequence, identity), 'z');
  568. const TString strings[] = {"one", "two", "three", "four"};
  569. UNIT_ASSERT_STRINGS_EQUAL(*MaxElementBy(strings, [](TString s) { return s.size(); }), "three");
  570. }
  571. Y_UNIT_TEST(TestMinElementBy) {
  572. const int array[] = {2, 3, 4, 1, 5};
  573. UNIT_ASSERT_VALUES_EQUAL(*MinElementBy(array, [](int x) -> char {
  574. return 'a' + x;
  575. }), 1);
  576. const TVector<int> vec(std::begin(array), std::end(array));
  577. UNIT_ASSERT_VALUES_EQUAL(*MinElementBy(vec, [](int x) {
  578. return -x;
  579. }), 5);
  580. int arrayMutable[] = {1, 2, 5, 3, 4, 5};
  581. auto minPtr = MinElementBy(arrayMutable, [](int x) { return x; });
  582. *minPtr += 100;
  583. UNIT_ASSERT_VALUES_EQUAL(*minPtr, 101);
  584. auto identity = [](char x) {
  585. return x;
  586. };
  587. auto singleElementSequence = {'z'};
  588. UNIT_ASSERT_VALUES_EQUAL(*MinElementBy(singleElementSequence, identity), 'z');
  589. const TVector<TStringBuf> strings = {"one", "two", "three", "four"};
  590. auto stringLength = [](TStringBuf s) {
  591. return s.size();
  592. };
  593. UNIT_ASSERT_STRINGS_EQUAL(*MinElementBy(strings, stringLength), "one");
  594. UNIT_ASSERT_STRINGS_EQUAL(*MinElementBy(strings.rbegin(), strings.rend(), stringLength), "two");
  595. }
  596. Y_UNIT_TEST(MaxElementByReturnsEndForEmptyRange) {
  597. const TVector<int> empty;
  598. UNIT_ASSERT_EQUAL(MaxElementBy(empty, [](int) { return 0; }), empty.end());
  599. }
  600. Y_UNIT_TEST(MaxElementByDoesntCallFunctorForEmptyRange) {
  601. const TVector<int> empty;
  602. auto functor = [](int) {
  603. UNIT_ASSERT(false);
  604. return 0;
  605. };
  606. MaxElementBy(empty, functor);
  607. }
  608. Y_UNIT_TEST(MinElementByReturnsEndForEmptyRange) {
  609. const TVector<int> empty;
  610. UNIT_ASSERT_EQUAL(MinElementBy(empty, [](int) { return 0; }), empty.end());
  611. }
  612. Y_UNIT_TEST(MinElementByDoesntCallFunctorForEmptyRange) {
  613. const TVector<int> empty;
  614. auto functor = [](int) {
  615. UNIT_ASSERT(false);
  616. return 0;
  617. };
  618. MinElementBy(empty, functor);
  619. }
  620. Y_UNIT_TEST(TestApplyToMany) {
  621. int res = 0;
  622. ApplyToMany([&res](auto v) { res += v; }, 1, 2, 3, 4, 5);
  623. UNIT_ASSERT_EQUAL(res, 15);
  624. struct TVisitor {
  625. TVisitor(int& acc)
  626. : Acc(acc)
  627. {
  628. }
  629. void operator()(const TString& s) {
  630. Acc += s.size();
  631. }
  632. void operator()(int v) {
  633. Acc += v * 2;
  634. }
  635. int& Acc;
  636. };
  637. TString s{"8-800-555-35-35"};
  638. ApplyToMany(TVisitor{res = 0}, 1, s, 5, s);
  639. UNIT_ASSERT_EQUAL(res, 12 + 2 * static_cast<int>(s.size()));
  640. }
  641. Y_UNIT_TEST(TestTupleForEach) {
  642. ForEach(std::tuple<>{}, [&](auto) { UNIT_ASSERT(false); });
  643. auto t = std::make_tuple(5, 6, 2, 3, 6);
  644. ForEach(t, [](auto& v) { v *= -1; });
  645. UNIT_ASSERT_EQUAL(t, std::make_tuple(-5, -6, -2, -3, -6));
  646. }
  647. Y_UNIT_TEST(TestTupleAllOf) {
  648. UNIT_ASSERT(AllOf(std::tuple<>{}, [](auto) { return false; }));
  649. UNIT_ASSERT(!AllOf(std::make_tuple(1, 2, 0, 4, 5), [&](auto v) { UNIT_ASSERT_LT(v, 3); return 0 != v; }));
  650. UNIT_ASSERT(AllOf(std::make_tuple(1, 2, 3, 4, 5), [](auto v) { return 0 != v; }));
  651. {
  652. auto pred = std::function<bool(int)>([x = TVector<int>(1, 0)](auto v) { return x.front() != v; });
  653. UNIT_ASSERT(AllOf(std::make_tuple(1, 2), pred));
  654. UNIT_ASSERT(AllOf(std::make_tuple(1, 2), pred));
  655. }
  656. {
  657. auto ts = std::make_tuple(TString{"foo"}, TString{"bar"});
  658. auto pred = [](auto s) { return s.size() == 3; };
  659. UNIT_ASSERT_VALUES_EQUAL(AllOf(ts, pred), AllOf(ts, pred));
  660. }
  661. }
  662. Y_UNIT_TEST(TestTupleAnyOf) {
  663. UNIT_ASSERT(!AnyOf(std::tuple<>{}, [](auto) { return true; }));
  664. UNIT_ASSERT(AnyOf(std::make_tuple(0, 1, 2, 3, 4), [&](auto v) { UNIT_ASSERT_LT(v, 2); return 1 == v; }));
  665. UNIT_ASSERT(AnyOf(std::make_tuple(1, 2, 3, 4, 5), [](auto v) { return 5 == v; }));
  666. auto pred = std::function<bool(int)>([x = TVector<int>(1, 0)](auto v) { return x.front() == v; });
  667. UNIT_ASSERT(!AnyOf(std::make_tuple(1, 2), pred));
  668. UNIT_ASSERT(!AnyOf(std::make_tuple(1, 2), pred));
  669. {
  670. auto ts = std::make_tuple(TString{"f"}, TString{"bar"});
  671. auto pred = [](auto s) { return s.size() == 3; };
  672. UNIT_ASSERT_VALUES_EQUAL(AnyOf(ts, pred), AnyOf(ts, pred));
  673. }
  674. }
  675. Y_UNIT_TEST(FindIfForContainer) {
  676. using std::begin;
  677. using std::end;
  678. int array[] = {1, 2, 3, 4, 5};
  679. UNIT_ASSERT_EQUAL(FindIf(array, [](int x) { return x == 1; }), begin(array));
  680. UNIT_ASSERT_EQUAL(FindIf(array, [](int x) { return x > 5; }), end(array));
  681. TVector<int> vector = {1, 2, 3, 4, 5};
  682. UNIT_ASSERT_EQUAL(FindIf(vector, [](int x) { return x == 1; }), begin(vector));
  683. UNIT_ASSERT_EQUAL(FindIf(vector, [](int x) { return x > 5; }), end(vector));
  684. // Compilability test. Check if the returned iterator is non const
  685. auto iter = FindIf(vector, [](int x) { return x == 1; });
  686. *iter = 5;
  687. // Compilability test. Check if the returned iterator is const. Should not compile
  688. const TVector<int> constVector = {1, 2, 3, 4, 5};
  689. auto constIter = FindIf(constVector, [](int x) { return x == 1; });
  690. Y_UNUSED(constIter);
  691. // *constIter = 5;
  692. }
  693. struct TRange {
  694. };
  695. const TRange* begin(const TRange& r) {
  696. return &r;
  697. }
  698. const TRange* end(const TRange& r) {
  699. return &r + 1;
  700. }
  701. Y_UNIT_TEST(FindIfForUserType) {
  702. // Compileability test. Should work for user types with begin/end overloads
  703. TRange range;
  704. auto i = FindIf(range, [](auto) { return false; });
  705. Y_UNUSED(i);
  706. }
  707. Y_UNIT_TEST(TestLowerBoundBy) {
  708. using TIntPairs = TVector<std::pair<i32, i32>>;
  709. auto data = TIntPairs{{1, 5}, {3, 2}, {3, 4}, {8, 0}, {5, 4}};
  710. auto getKey = [](const auto& x) { return x.second; };
  711. StableSortBy(data, getKey);
  712. auto it = LowerBoundBy(data.begin(), data.end(), 4, getKey);
  713. UNIT_ASSERT(it != data.end());
  714. UNIT_ASSERT_EQUAL(it->second, 4);
  715. UNIT_ASSERT_EQUAL(it->first, 3);
  716. UNIT_ASSERT(it > data.begin());
  717. UNIT_ASSERT_EQUAL((it - 1)->second, 2);
  718. UNIT_ASSERT((it + 1) < data.end());
  719. UNIT_ASSERT_EQUAL((it + 1)->second, 4);
  720. }
  721. Y_UNIT_TEST(TestUpperBoundBy) {
  722. using TIntPairs = TVector<std::pair<i32, i32>>;
  723. auto data = TIntPairs{{1, 5}, {3, 2}, {3, 4}, {8, 0}, {5, 4}};
  724. auto getKey = [](const auto& x) { return x.second; };
  725. StableSortBy(data, getKey);
  726. auto it = UpperBoundBy(data.begin(), data.end(), 4, getKey);
  727. UNIT_ASSERT(it != data.end());
  728. UNIT_ASSERT_EQUAL(it->second, 5);
  729. UNIT_ASSERT_EQUAL(it->first, 1);
  730. UNIT_ASSERT(it > data.begin());
  731. UNIT_ASSERT_EQUAL((it - 1)->second, 4);
  732. UNIT_ASSERT((it + 1) == data.end());
  733. }
  734. Y_UNIT_TEST(TestFindInContainer) {
  735. std::vector<int> v = {1, 2, 1000, 15, 100};
  736. UNIT_ASSERT(Find(v, 5) == v.end());
  737. UNIT_ASSERT(Find(v, 1) == v.begin());
  738. UNIT_ASSERT(Find(v, 100) == v.end() - 1);
  739. }
  740. Y_UNIT_TEST(AccumulateWithBinOp) {
  741. std::vector<int> v = {1, 2, 777};
  742. UNIT_ASSERT_VALUES_EQUAL(TString("begin;1;2;777"), Accumulate(v, TString("begin"), [](auto&& a, auto& b) { return a + ";" + ToString(b); }));
  743. }
  744. }