@@ -37,28 +37,93 @@ int main() {
3737 * Particularly important because of the copy and swap idiom.
3838 */
3939
40- // # randomize
40+ // # random_shuffle
4141 {
4242 std::vector<int > v{2 , 0 , 1 };
4343 std::random_shuffle (v.begin (), v.end ());
4444 }
4545
46- // # copy
46+ #if __cplusplus >= 201703L
47+ /* # sample
48+ *
49+ * https://stackoverflow.com/questions/6942273/how-to-get-a-random-element-from-a-c-container/42484107#42484107
50+ */
4751 {
48- std::vector<int > v{2 , 0 , 1 };
49- std::vector<int > v2 (5 , 3 );
50- std::copy (v.begin (), v.end (), v2.begin () + 1 );
51- assert (v2 == std::vector<int >({3 , 2 , 0 , 1 , 3 }));
52+ const std::vector<int > in{1 , 2 , 3 , 5 , 7 };
53+ std::vector<int > out;
54+ size_t nelems = 3 ;
55+ std::sample (in.begin (), in.end (), std::back_inserter (out),
56+ nelems, std::mt19937{std::random_device{}()});
57+ std::set in_set (std::begin (in), std::end (in));
58+ std::set out_set (std::begin (out), std::end (out));
59+
60+ // The sample elements are distinct.
61+ assert (out_set.size () == nelems);
62+
63+ // The sample elements came from the input.
64+ std::set<int > intersect;
65+ std::set_intersection (
66+ in.begin (), in.end (), out.begin (), out.end (),
67+ std::inserter (intersect, intersect.begin ())
68+ );
69+ assert (intersect.size () == nelems);
70+
71+ // for (auto i : out)
72+ // std::cout << i << std::endl;
5273 }
74+ #endif
5375
5476 /* # equal
5577 *
5678 * Compares ranges of two containers.
79+ *
80+ * Vs memcmp:
81+ * https://stackoverflow.com/questions/39262496/why-is-stdequal-much-slower-than-a-hand-rolled-loop-for-two-small-stdarray
5782 */
5883 {
59- std::vector<int > v {0 , 1 , 2 };
84+ std::vector<int > v1 {0 , 1 , 2 };
6085 std::vector<int > v2{ 1 , 2 , 3 };
61- assert (std::equal (v.begin () + 1 , v.end (), v2.begin ()));
86+ assert (std::equal (v1.begin () + 1 , v1.end (), v2.begin ()));
87+ }
88+
89+ /* # copy
90+ *
91+ * Vs memcpy: can compile down to an assembly optimized memcpy for arrays apparently, so just always use this:
92+ * https://stackoverflow.com/questions/4707012/is-it-better-to-use-stdmemcpy-or-stdcopy-in-terms-to-performance
93+ */
94+ {
95+ /* Newbie basic class usage. */
96+ {
97+ std::vector<int > v{0 , 1 , 2 , 3 , 4 };
98+ std::vector<int > v2 (v.size (), v.size ());
99+ std::copy (v.begin () + 1 , v.end () - 1 , v2.begin () + 2 );
100+ assert (v2 == std::vector<int >({5 , 5 , 1 , 2 , 3 }));
101+ }
102+
103+ /* # std::begin
104+ *
105+ * # std::end
106+ *
107+ * Array usage.
108+ *
109+ * https://stackoverflow.com/questions/7593086/why-use-non-member-begin-and-end-functions-in-c11
110+ */
111+ {
112+ int v1[]{0 , 1 , 2 , 3 , 4 };
113+ int v2[]{5 , 5 , 5 , 5 , 5 };
114+ int v3[]{5 , 5 , 1 , 2 , 3 };
115+ std::copy (std::begin (v1) + 1 , std::end (v1) - 1 , std::begin (v2) + 2 );
116+ assert (std::equal (std::begin (v2), std::end (v2), std::begin (v3)));
117+ }
118+
119+ /* Therefore, a more elegant class approach that uses exact same syntax as arrays. */
120+ {
121+ std::vector<int > v1{0 , 1 , 2 , 3 , 4 };
122+ std::vector<int > v2{5 , 5 , 5 , 5 , 5 };
123+ std::vector<int > v3{5 , 5 , 1 , 2 , 3 };
124+ std::copy (std::begin (v1) + 1 , std::end (v1) - 1 , std::begin (v2) + 2 );
125+ assert (std::equal (std::begin (v2), std::end (v2), std::begin (v3)));
126+ }
62127 }
63128
64129 /* # accumulate
@@ -125,7 +190,6 @@ int main() {
125190 * If you want to get the position of those items, use `equal_range`, `lower_bound` or `upper_bound`.
126191 */
127192 {
128-
129193 std::vector<int > v{0 , 1 , 2 };
130194 assert (std::binary_search (v.begin (), v.end (), 1 ) == true );
131195 assert (std::binary_search (v.begin (), v.end (), 3 ) == false );
0 commit comments