└── README.md /README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | This is the list of modern CPP tricks often used in Coding Interviews and Competitive Programming. 3 | If you like Rachit's work, you can follow at - 4 | - Discord - https://bit.ly/discord-rachit 5 | - Programming YouTube Channel - https://bit.ly/rachityoutube 6 | 7 | ## Contents: 8 | - [No more nested `min(x, min(y, ...))`](#no-more-nested-minx-miny-) 9 | - [JavaScript like Destructuring using Structured Binding in C++](#javascript-like-destructuring-using-structured-binding-in-c) 10 | - [Powerful Logging and Debugging](#powerful-logging-and-debugging) 11 | - [How debug macros work?](#how-debug-macros-work) 12 | - [The Problem with this macro - its not scalable](#the-problem-with-this-macro---its-not-scalable) 13 | - [Solution using a powerful macro](#solution-using-a-powerful-macro) 14 | - [Generic Reader and Writer for multiple variables and containers](#generic-reader-and-writer-for-multiple-variables-and-containers) 15 | - [Usage](#usage) 16 | - [Decorators in C++ and Multiple Parameters](#decorators-in-c-and-multiple-parameters) 17 | - [Live Demo on YouTube](#live-demo-on-youtube) 18 | - [Printing as many variables in one line](#printing-as-many-variables-in-one-line) 19 | - [Powerful decorator functions in C++](#powerful-decorator-functions-in-c) 20 | - [Exploiting decorators by nesting them](#exploiting-decorators-by-nesting-them) 21 | - [Sets and Maps Tricks](#sets-and-maps-tricks) 22 | - [`s.contains` vs `s.find(...) != s.end`](#scontains-vs-sfind--send) 23 | - [`multiset.extract` vs `multiset.erase(multiset.find(...))`](#multisetextract-vs-multiseterasemultisetfind) 24 | 25 | 26 | ## No more nested `min(x, min(y, ...))` 27 | Use initializer list and `std::min` and `std::max` to make life easy 28 | ```cpp 29 | small = min(x, min(y, min(z, k))); // the old way 30 | small = min({x, y, z, k}); // life is easy 31 | ``` 32 | 33 | ## JavaScript like Destructuring using Structured Binding in C++ 34 | ```cpp 35 | pair cur = {1, 2}; 36 | auto [x, y] = cur; 37 | // x is now 1, y is now 2 38 | // no need of cur.first and cur.second 39 | 40 | array arr = {1, 0, -1}; 41 | auto [a, b, c] = arr; 42 | // a is now 1, b is now 0, c is now -1 43 | ``` 44 | 45 | 46 | ---------------- 47 | 48 | 49 | ## Powerful Logging and Debugging 50 | 51 | ### How debug macros work? 52 | Straight to the point, I have often used the `debug` macro which stringifies the variable names and their values. 53 | 54 | ```cpp 55 | #define deb(x) cout << #x << " " << x 56 | int ten = 10; 57 | deb(ten); // prints "ten = 10" 58 | ``` 59 | 60 | This is often useful in debugging. 61 | 62 | ### The Problem with this macro - its not scalable 63 | However, when you have multiple variables to log, you end up with more `deb2` and `deb3` macros. 64 | 65 | ```cpp 66 | #define deb(x) cout << #x << " " << x 67 | #define deb2(x) cout << #x << " " << x << " " << #y << " " << y 68 | #define deb3(x, y, z) cout << #x << " " << x << " " << #y << " " << y << " " << #z << " " << z 69 | ``` 70 | 71 | This is not scalable. 72 | 73 | ### Solution using a powerful macro 74 | Here is the solution using variadic macros and fold expressions, 75 | 76 | ```cpp 77 | #define deb(...) logger(#__VA_ARGS__, __VA_ARGS__) 78 | template 79 | void logger(string vars, Args&&... values) { 80 | cout << vars << " = "; 81 | string delim = ""; 82 | (..., (cout << delim << values, delim = ", ")); 83 | } 84 | 85 | int xx = 3, yy = 10, xxyy = 103; 86 | deb(xx); // prints "xx = 3" 87 | deb(xx, yy, xxyy); // prints "xx, yy, xxyy = 3, 10, 103" 88 | ``` 89 | 90 | 91 | ---------------- 92 | 93 | 94 | ## Generic Reader and Writer for multiple variables and containers 95 | ```cpp 96 | template 97 | void read(T &...args) { 98 | ((cin >> args), ...); 99 | } 100 | 101 | template 102 | void write(string delimiter, T &&...args) { 103 | ((cout << args << delimiter), ...); 104 | } 105 | 106 | template 107 | void readContainer(T &t) { 108 | for (auto &e : t) { 109 | read(e); 110 | } 111 | } 112 | 113 | template 114 | void writeContainer(string delimiter, T &t) { 115 | for (const auto &e : t) { 116 | write(delimiter, e); 117 | } 118 | write("\n"); 119 | } 120 | ``` 121 | ### Usage 122 | ```cpp 123 | // Question: read three space seprated integers and print them in different lines. 124 | int x, y, z; 125 | read(x, y, z); 126 | write("\n", x, y, z); 127 | 128 | // even works with variable data types :) 129 | int n; 130 | string s; 131 | read(n, s); 132 | write(" ", s, "has length", n, "\n"); 133 | 134 | // Question: read an array of `N` integers and print it to the output console. 135 | int N; 136 | read(N); 137 | vector arr(N); 138 | readContainer(arr); 139 | writeContainer(" ", arr); // output: arr[0] arr[1] arr[2] ... arr[N - 1] 140 | writeContainer("\n", arr); 141 | /** 142 | * output: 143 | * arr[0] 144 | * arr[1] 145 | * arr[2] 146 | * ... 147 | * ... 148 | * ... 149 | * arr[N - 1] 150 | */ 151 | ``` 152 | 153 | 154 | ---------------- 155 | 156 | 157 | ## Decorators in C++ and Multiple Parameters 158 | 159 | ### Live Demo on YouTube 160 | - Check the online demo on YouTube [here on Rachit's channel](https://www.youtube.com/watch?v=ZhWyNjPGXD4). 161 | 162 | 163 | ### Printing as many variables in one line 164 | ```cpp 165 | template 166 | void printer(T&&... args) { 167 | ((cout << args << " "), ...); 168 | } 169 | 170 | int age = 25; 171 | string name = "Rachit"; 172 | printer("I am", name, ',', age, "years old"); 173 | // ^ This prints the following 174 | // I am Rachit, 25 years old 175 | ``` 176 | 177 | ### Powerful decorator functions in C++ 178 | ```cpp 179 | template 180 | auto debug_func(const F& func) { 181 | return [func](auto &&...args) { // forward reference 182 | cout << "input = "; 183 | printer(args...); 184 | auto res = func(forward(args)...); 185 | cout << "res = " << res << endl; 186 | return res; 187 | }; 188 | } 189 | 190 | debug_func(pow)(2, 3); 191 | // ^ this automatically prints 192 | // input = 2 3 res = 8 193 | ``` 194 | 195 | ### Exploiting decorators by nesting them 196 | Lets define another decorator `beautify` as follows. 197 | ```cpp 198 | template 199 | auto beautify(const F& func) { 200 | return [func](auto &&...args) { // forward reference 201 | cout << "========" << endl; 202 | func(forward(args)...); 203 | cout << "========" << endl; 204 | }; 205 | } 206 | 207 | beautify(debug_func(pow(2, 3))); 208 | // ^ this now prints 209 | // ======== 210 | // input = 2 3 res = 8 211 | // ======== 212 | ``` 213 | Its amazing how much you can do by writing such generic decorators and nest them. 214 | Think about decorators like `log_time` that calculates the time taken for a given function. 215 | 216 | ## Sets and Maps Tricks 217 | 218 | ### `s.contains` vs `s.find(...) != s.end` 219 | ``` 220 | set example{1, 2, 3, 4}; 221 | example.find(3) != example.end() // true 222 | example.contains(3) // true 223 | ``` 224 | 225 | Note that this works with `map` as well as `set`. 226 | 227 | ### `multiset.extract` vs `multiset.erase(multiset.find(...))` 228 | ``` 229 | multiset mset{1, 1, 2, 2, 3, 3}; 230 | mset.erase(1); // {2, 2, 3, 3} deleted all 1s 231 | mset.erase(mset.find(2)) // {2, 3, 3} need to use erase + find 232 | mset.extract(3) // {2, 3} simple and clean 233 | ``` 234 | 235 | * `multiset::extract` helps remove single instance naturally. 236 | * Note this also works with normal `set` and `map`. 237 | * It returns a node handle --------------------------------------------------------------------------------