algorithm.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. // TODO: need a test file per header and include the header first, to detect missing includes
  2. #include "simple/support/algorithm.hpp"
  3. #include <cassert>
  4. #include <string>
  5. #include <vector>
  6. #include <numeric>
  7. #include <cctype>
  8. #include <array>
  9. #include "simple/support/iterator/match.hpp" // match_iterator
  10. #include "simple/support/misc.hpp" // is_space
  11. using namespace simple;
  12. using namespace support;
  13. void MultidimentionalIteration()
  14. {
  15. using std::rbegin;
  16. using std::rend;
  17. using Vector = std::array<int, 3>;
  18. const auto lower = Vector{13,3,-20};
  19. const auto upper = Vector{45,32,12};
  20. std::vector<Vector> test_data;
  21. std::vector<Vector> data;
  22. for(int k = lower[2]; k < upper[2]; ++k)
  23. for(int j = lower[1]; j < upper[1]; ++j)
  24. for(int i = lower[0]; i < upper[0]; ++i)
  25. test_data.push_back({i,j,k});
  26. auto i = lower;
  27. auto magnitude = i.begin();
  28. while(magnitude != i.end())
  29. {
  30. data.push_back(i);
  31. magnitude = advance_vector(i, lower, upper);
  32. }
  33. assert(data == test_data);
  34. test_data.clear();
  35. data.clear();
  36. Vector step = {1,2,3};
  37. for(int k = lower[2]; k < upper[2]; k += step[2])
  38. for(int j = lower[1]; j < upper[1]; j += step[1])
  39. for(int i = lower[0]; i < upper[0]; i += step[0])
  40. test_data.push_back({i,j,k});
  41. i = lower;
  42. magnitude = i.begin();
  43. while(magnitude != i.end())
  44. {
  45. data.push_back(i);
  46. magnitude = advance_vector(i, lower, upper, step);
  47. }
  48. assert(data == test_data);
  49. test_data.clear();
  50. data.clear();
  51. for(int k = 0; k < upper[2]; ++k)
  52. for(int j = 0; j < upper[1]; ++j)
  53. for(int i = 0; i < upper[0]; ++i)
  54. test_data.push_back({i,j,k});
  55. i = Vector{};
  56. magnitude = i.begin();
  57. while(magnitude != i.end())
  58. {
  59. data.push_back(i);
  60. magnitude = advance_vector(i, upper);
  61. }
  62. assert(data == test_data);
  63. }
  64. void ContainerAsNumber()
  65. {
  66. using num = std::vector<int>;
  67. const std::vector<std::pair<num, int>> numbers {
  68. {{0,0,0,0}, 0}, // 0
  69. {{1,0,0,0}, 1}, // 1
  70. {{0,1,0,0}, 0}, // 2
  71. {{1,1,0,0}, 2}, // 3
  72. {{0,0,1,0}, 0}, // 4
  73. {{1,0,1,0}, 1}, // 5
  74. {{0,1,1,0}, 0}, // 6
  75. {{1,1,1,0}, 3}, // 7
  76. {{0,0,0,1}, 0}, // 8
  77. {{1,0,0,1}, 1}, // 9
  78. {{0,1,0,1}, 0}, // A
  79. {{1,1,0,1}, 2}, // B
  80. {{0,0,1,1}, 0}, // C
  81. {{1,0,1,1}, 1}, // D
  82. {{0,1,1,1}, 0}, // E
  83. {{1,1,1,1}, 4}, // F
  84. };
  85. num n = numbers.front().first;
  86. for(auto& [number, carry] : numbers)
  87. {
  88. assert(n == number);
  89. assert( next_number(n) - n.begin() == carry );
  90. }
  91. for(auto& [number, carry] : reverse_range(numbers))
  92. {
  93. assert( prev_number(n) - n.begin() == carry );
  94. assert( n == number );
  95. }
  96. }
  97. void IteratorRange()
  98. {
  99. array<int, 10> arr {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  100. array<int, 5> sub_array{3, 4, 5, 6, 7};
  101. array<int, 5> sub_array_2{5, 6, 7, 8, 9};
  102. array<int, 5> sub_array_3{0, 1, 2, 3, 4};
  103. array<int, 5> rsub_array_2{9, 8, 7, 6, 5};
  104. int i = 0;
  105. for(auto&& element : get_iterator_range(arr, {3, 8}))
  106. assert(sub_array[i++] == element);
  107. i = 0;
  108. for(auto&& element : get_iterator_range(arr, {5, 800}))
  109. assert(sub_array_2[i++] == element);
  110. i = arr.size();;
  111. for(auto&& element : reverse_range(arr))
  112. assert(arr[--i] == element);
  113. i = 0;
  114. for(auto&& element : reverse(get_iterator_range(arr, {5, 800})))
  115. assert(rsub_array_2[i++] == element);
  116. i = 0;
  117. for(auto&& element : get_iterator_range<int>(arr, {-105, 5}))
  118. assert(sub_array_3[i++] == element);
  119. i = 0;
  120. for(auto&& element : get_iterator_range<int>(arr, {-105, 105}))
  121. assert(arr[i++] == element);
  122. }
  123. void Variance()
  124. {
  125. array<int, 10> arr {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  126. auto var = arr;
  127. assert( variance(var).end() == var.end()-1 );
  128. assert( (var == array<int, 10>{1, 1, 1, 1, 1, 1, 1, 1, 1, 9}) );
  129. auto pair_sum = arr;
  130. variance(pair_sum, std::plus{});
  131. assert( (pair_sum == array<int, 10>{1, 3, 5, 7, 9, 11, 13, 15, 17, 9}) );
  132. array<int, 40> fib {1};
  133. std::adjacent_difference(fib.begin(), fib.end()-1, fib.begin()+1, std::plus{});
  134. auto varfib = fib;
  135. variance(varfib);
  136. assert( (std::equal(varfib.begin()+1, varfib.end() -1, fib.begin())) );
  137. }
  138. void Average()
  139. {
  140. static_assert( average(1,2,3) == 2 );
  141. static_assert( average(1,2,3,4.f) == 10.f/4.f );
  142. static_assert( noexcept(average(1,2,3)) );
  143. static_assert( noexcept(average(1,2.0,3.f)) );
  144. }
  145. constexpr bool Constexprness()
  146. {
  147. range<int> v{};
  148. range<int*> vitr{};
  149. (void)get_iterator_range(v.bounds, v);
  150. (void)make_range(v.bounds);
  151. (void)reverse_range(v.bounds);
  152. (void)reverse(vitr);
  153. auto itr = v.bounds.begin();
  154. advance_vector(itr,itr,itr);
  155. advance_vector(itr,itr,itr,itr);
  156. advance_vector(itr,itr,itr,itr,itr);
  157. advance_vector(v.bounds, v.bounds);
  158. advance_vector(v.bounds, v.bounds, v.bounds);
  159. advance_vector(v.bounds, v.bounds, v.bounds, v.bounds);
  160. next_number(v.bounds);
  161. prev_number(v.bounds);
  162. variance(v.bounds);
  163. void(wrap(1,1));
  164. void(midpoint(1,1));
  165. void(average(1,1));
  166. return true;
  167. }
  168. namespace adl_range_test
  169. {
  170. struct segment
  171. {
  172. int* start;
  173. int size;
  174. };
  175. int* begin(const segment& x) { return x.start; }
  176. int* end(const segment& x) { return x.start + x.size; }
  177. }
  178. template <typename T> class show;
  179. void TypeTraits()
  180. {
  181. static_assert(is_range_v<int(&)[2]>);
  182. static_assert(!is_range_v<int[2]>);
  183. static_assert(is_range_v<std::array<int,2>>);
  184. static_assert(is_range_v<std::array<int,2>&>);
  185. static_assert(is_range_v<adl_range_test::segment>);
  186. }
  187. void Search()
  188. {
  189. {
  190. char x[] = "aaab";
  191. char y[] = "aab";
  192. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).begin() == x + 1);
  193. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).end() == std::end(x));
  194. assert(*(std::end(x) - 1) == '\0');
  195. }
  196. {
  197. char x[] = "aaab";
  198. char y[] = "aba";
  199. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).begin() == std::end(x));
  200. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).end() == std::end(x));
  201. }
  202. {
  203. std::array<char,4> x = {'a','a','a','b'};
  204. char y[] = "aba";
  205. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).begin() == std::end(x));
  206. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).end() == std::end(x));
  207. }
  208. {
  209. std::array<char,4> x = {'a','a','a','b'};
  210. std::array<char,3> y = {'a','b','a'};
  211. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).begin() == std::end(x));
  212. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).end() == std::end(x));
  213. }
  214. {
  215. char x[] = "aaab";
  216. std::array<char,0> y{};
  217. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).begin() == std::begin(x));
  218. assert(support::search(std::begin(x), std::end(x), std::begin(y), std::end(y)).end() == std::begin(x));
  219. }
  220. }
  221. auto split(std::string_view view, const std::string& separator)
  222. {
  223. std::vector<string_view> result;
  224. support::split(view, separator, std::back_inserter(result));
  225. return result;
  226. }
  227. auto split_words(std::string_view view)
  228. {
  229. std::vector<string_view> result;
  230. support::split(view, match_iterator(is_space), std::back_inserter(result));
  231. return result;
  232. }
  233. auto split_one_or_two_slash(std::string_view view)
  234. {
  235. std::vector<string_view> result;
  236. struct{
  237. int match_count = 0;
  238. bool operator()() const { return match_count == 2 || match_count == 1; };
  239. bool operator()(char c)
  240. {
  241. bool match = c == '/' || c == '\\';
  242. match_count += match;
  243. return match;
  244. };
  245. } matcher{};
  246. support::split(view, match_iterator(std::move(matcher)), std::back_inserter(result));
  247. return result;
  248. }
  249. void Split()
  250. {
  251. assert(( ::split("a--b--c", "--") == std::vector<string_view>{"a", "b", "c"} ));
  252. assert(( ::split("a--b--c--", "--") == std::vector<string_view>{"a", "b", "c", ""} ));
  253. assert(( ::split("--a--b--c", "--") == std::vector<string_view>{"", "a", "b", "c"} ));
  254. assert(( ::split("--a--b--c--", "--") == std::vector<string_view>{"", "a", "b", "c", ""} ));
  255. assert(( ::split("--""--""--""--""--a--b--c--", "--") == std::vector<string_view>{"", "", "", "", "", "a", "b", "c", ""} ));
  256. assert(( ::split("--", "--") == std::vector<string_view>{"", ""} ));
  257. assert(( ::split("----", "--") == std::vector<string_view>{"", "", ""} ));
  258. assert(( ::split("---", "--") == std::vector<string_view>{"", "-"} ));
  259. assert(( ::split("", "--") == std::vector<string_view>{""} ));
  260. assert(( ::split_words("hey there words") == std::vector<string_view>{"hey", "there", "words"} ));
  261. assert(( ::split_words("hey there\twords") == std::vector<string_view>{"hey", "there", "words"} ));
  262. assert(( ::split_words(" hey \n there\twords") == std::vector<string_view>{"", "hey", "there", "words"} ));
  263. assert(( ::split_words("\t hey \n there words\n") == std::vector<string_view>{"", "hey", "there", "words", ""} ));
  264. assert(( ::split_words("") == std::vector<string_view>{""} ));
  265. assert(( ::split_words(" ") == std::vector<string_view>{"",""} ));
  266. assert(( ::split_words(" ") == std::vector<string_view>{"",""} ));
  267. // no idea if this makes any sense, just testing a stateful matcher
  268. assert(( ::split_one_or_two_slash("hey//there/\\slashes") == std::vector<string_view>{"hey", "there", "slashes"} ));
  269. assert(( ::split_one_or_two_slash("hey/there///slashes") == std::vector<string_view>{"hey", "there/", "slashes"} ));
  270. assert(( ::split_one_or_two_slash("/") == std::vector<string_view>{"", ""} ));
  271. assert(( ::split_one_or_two_slash("//") == std::vector<string_view>{"", ""} ));
  272. assert(( ::split_one_or_two_slash("///") == std::vector<string_view>{"///"} ));
  273. assert(( ::split_one_or_two_slash("////") == std::vector<string_view>{"////"} ));
  274. assert(( ::split_one_or_two_slash("/////") == std::vector<string_view>{"/////"} ));
  275. }
  276. void SetDifference()
  277. {
  278. {
  279. std::array x {1,2,2,3,4,5};
  280. std::array y {2,4};
  281. std::array<int, 4> z;
  282. std::array<int, 3> w;
  283. support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(z));
  284. support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(w));
  285. assert(( z == std::array{1,2,3,5} ));
  286. assert(( w == std::array{1,3,5} ));
  287. }
  288. {
  289. std::array x {5,4,3,2,2,1};
  290. std::array y {4,2};
  291. std::array<int, 4> z;
  292. std::array<int, 3> w;
  293. support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(z), std::greater<>{});
  294. support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(w), std::greater<>());
  295. assert(( z == std::array{5,3,2,1} ));
  296. assert(( w == std::array{5,3,1} ));
  297. }
  298. {
  299. std::array x {1,2,2,3,4,5};
  300. std::array y {2,4};
  301. auto diff_end = support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  302. std::array diff{1,2,3,5};
  303. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  304. }
  305. {
  306. std::array x {1,2,2,3,4,5};
  307. std::array y {2,4};
  308. auto diff_end = support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  309. std::array diff{1,3,5};
  310. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  311. }
  312. {
  313. std::array x {1,2,2,3,4,5};
  314. std::array y {2,2,4,4,4};
  315. auto diff_end = support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  316. std::array diff{1,3,5};
  317. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  318. }
  319. {
  320. std::array x {1,2,2,3,4,5};
  321. std::array<int,0> y {};
  322. auto diff_end = support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  323. std::array diff{1,2,2,3,4,5};
  324. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  325. diff_end = support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  326. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  327. }
  328. {
  329. std::array<int,0> x {};
  330. std::array y {1,2,3};
  331. auto diff_end = support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  332. std::array<int,0> diff{};
  333. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  334. diff_end = support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  335. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  336. }
  337. {
  338. std::array x {1,2,3};
  339. std::array y {1,2,3};
  340. auto diff_end = support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  341. std::array<int,0> diff{};
  342. assert( std::begin(x) == diff_end );
  343. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  344. diff_end = support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  345. assert( std::begin(x) == diff_end );
  346. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  347. }
  348. {
  349. std::array x {1,2,3};
  350. std::array y {1,2,3,4,5,6};
  351. auto diff_end = support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  352. std::array<int,0> diff{};
  353. assert( std::begin(x) == diff_end );
  354. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  355. diff_end = support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  356. assert( std::begin(x) == diff_end );
  357. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  358. }
  359. {
  360. std::array x {12,12,12,12,12,12,12};
  361. std::array y {12,12,12,12,12,12};
  362. auto diff_end = support::set_difference(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  363. std::array diff{12};
  364. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  365. }
  366. {
  367. std::array x {12,12,12,12,12,12,12};
  368. std::array y {12,12,12,12,12,12};
  369. auto diff_end = support::set_difference<support::ignore_count>(std::begin(x), std::end(x), std::begin(y), std::end(y), std::begin(x));
  370. std::array<int,0> diff{};
  371. assert( std::begin(x) == diff_end );
  372. assert( std::equal(std::begin(x), diff_end, std::begin(diff)) );
  373. }
  374. }
  375. void PickUnqiue()
  376. {
  377. const std::array a
  378. {
  379. 1.0, 1.1, 1.2,
  380. 2.0, 2.1,
  381. 3.0, 3.1, 3.2, 3.3,
  382. 4.0,
  383. 5.0, 5.1, 5.2
  384. };
  385. std::array<double,5> first;
  386. pick_unique(a, std::equal_to<int>(), [](auto r){ return r.begin(); }, first.begin());
  387. assert(( first == std::array{1.0, 2.0, 3.0, 4.0, 5.0}) );
  388. std::array<double,5> last;
  389. pick_unique(a, std::equal_to<int>(), [](auto r){ return std::prev(r.end()); }, last.begin());
  390. assert(( last == std::array{1.2, 2.1, 3.3, 4.0, 5.2}) );
  391. std::array<double,5> middle;
  392. pick_unique(a, std::equal_to<int>(), [](auto r){ return midpoint(r); }, middle.begin());
  393. assert(( middle == std::array{1.1, 2.1, 3.2, 4.0, 5.1}) );
  394. }
  395. void Repeat()
  396. {
  397. assert(repeat<4>(1,0,std::plus<>{}) == 4);
  398. assert(repeat<12>(4,0,std::plus<>{}) == 48);
  399. assert(repeat<2>(3,1,std::multiplies<>{}) == 9);
  400. assert(repeat<3>(2,1,std::multiplies<>{}) == 8);
  401. assert(repeat<10>(2,1,std::multiplies<>{}) == 1024);
  402. assert(repeat<9>(3,1,std::multiplies<>{}) == 19683);
  403. }
  404. int main()
  405. {
  406. MultidimentionalIteration();
  407. ContainerAsNumber();
  408. IteratorRange();
  409. Variance();
  410. Average();
  411. static_assert(Constexprness());
  412. TypeTraits();
  413. Search();
  414. Split();
  415. SetDifference();
  416. PickUnqiue();
  417. Repeat();
  418. return 0;
  419. }