|
| 1 | +# PA C++ - TLDR |
| 2 | + |
| 3 | +## PA skel |
| 4 | +During the PA laboratories, you'll receive a skeleton for each task. |
| 5 | + |
| 6 | +```cpp |
| 7 | +#include <bits/stdc++.h> |
| 8 | +using namespace std; |
| 9 | + |
| 10 | +class Task { |
| 11 | +public: |
| 12 | + void solve() { |
| 13 | + read_input(); |
| 14 | + get_result(); |
| 15 | + print_output(); |
| 16 | + } |
| 17 | + |
| 18 | +private: |
| 19 | + // TODO: define members |
| 20 | + |
| 21 | + void read_input() { |
| 22 | + ifstream fin("in"); |
| 23 | + // TODO: read input |
| 24 | + fin.close(); |
| 25 | + } |
| 26 | + |
| 27 | + void get_result() { |
| 28 | + // TODO: implement the solution |
| 29 | + } |
| 30 | + |
| 31 | + void print_output() { |
| 32 | + ofstream fout("out"); |
| 33 | + // TODO: write the solution |
| 34 | + fout.close(); |
| 35 | + } |
| 36 | +}; |
| 37 | + |
| 38 | +// [ATENTIE] NU modifica functia main! |
| 39 | +int main() { |
| 40 | + // * se aloca un obiect Task pe heap |
| 41 | + // (se presupune ca e prea mare pentru a fi alocat pe stiva) |
| 42 | + // * se apeleaza metoda solve() |
| 43 | + // (citire, rezolvare, printare) |
| 44 | + // * se distruge obiectul si se elibereaza memoria |
| 45 | + auto* task = new (std::nothrow) Task{}; // hint: cppreference/nothrow |
| 46 | + if (!task) { |
| 47 | + std::cerr << "new failed: WTF are you doing? Throw your PC!\n"; |
| 48 | + return -1; |
| 49 | + } |
| 50 | + task->solve(); |
| 51 | + delete task; |
| 52 | + return 0; |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +Notes: |
| 57 | +* You `don't` need to include other libraries. `<bits/stdc++.h>` includes everything! |
| 58 | +* You `don't` need to ever change the `main()` function! |
| 59 | +* You `need` to complete the implementation for the `Task` class. |
| 60 | + * The reading/writing must be done with `<fstream>` for performance reasonse. |
| 61 | + * Usually, the skeleton already implements the `read_input()` and `print_output()` methods. |
| 62 | + * You need to implement the `get_result()` method. |
| 63 | + * Optionally, you can add other helper methods to the class. |
| 64 | +* The `check` command compiles and runs the tasks. |
| 65 | + ```bash |
| 66 | + # compile and run all tasks for C++ |
| 67 | + ./check cpp |
| 68 | + |
| 69 | + # compile and run task-1 for C++ |
| 70 | + ./check cpp task-1 |
| 71 | + |
| 72 | + # compile and run test 1 for task-1 for C++ |
| 73 | + ./check cpp task-1 1 |
| 74 | + ``` |
| 75 | + |
| 76 | +## C++ tweaks |
| 77 | +### IO |
| 78 | +You should always use the C++ skel. |
| 79 | + |
| 80 | +```cpp |
| 81 | +// reading example: assume the input stream is named fin |
| 82 | +int x; |
| 83 | +fin >> x; // read integer x from file |
| 84 | + |
| 85 | +int x, y; |
| 86 | +fin >> x >> y; // read integers x and y from file |
| 87 | + |
| 88 | +int x; |
| 89 | +char c; |
| 90 | +std::string s; |
| 91 | +fin >> x >> c >> s; // read integer x, char c and string s from file |
| 92 | +``` |
| 93 | + |
| 94 | +```cpp |
| 95 | +// writing example: assume the output stream is named fout |
| 96 | +int x; |
| 97 | +fout << x; // write integer x to file |
| 98 | + |
| 99 | +int x, y; |
| 100 | +fout << x << " " << y << "\n"; // write a line: x, space, y, newline |
| 101 | + |
| 102 | +int x; |
| 103 | +char c; |
| 104 | +std::string s; |
| 105 | +fout << x " " << c << " " << s << "\n"; // write a line: x, space, y, space, s, newline |
| 106 | +``` |
| 107 | + |
| 108 | +### arrays |
| 109 | +You should always use `std::vector<T>`. |
| 110 | + |
| 111 | +```cpp |
| 112 | +// unitialized vector: |
| 113 | +// * use this when you don't know the size |
| 114 | +// * use push_back and pop_back to insert/remove elements |
| 115 | +std::vector<int> v{}; |
| 116 | +// read example |
| 117 | +for (int i = 0; i < n; ++i) { |
| 118 | + int x; |
| 119 | + fin >> x; |
| 120 | + v.push_back(x); |
| 121 | +} |
| 122 | + |
| 123 | +// vector with n zeros (0-indexed) |
| 124 | +std::vector<int> v{n, 0}; // use: v[0], v[1], ... , v[n - 1] |
| 125 | +// read example |
| 126 | +for (int i = 0; i < n; ++i) { |
| 127 | + fin >> v[i]; |
| 128 | +} |
| 129 | + |
| 130 | +// vector with n zeros (1-indexed) |
| 131 | +std::vector<int> v{n + 1, 0}; // use: v[1], v[2], ..., v[n] - e.g. for dynamic programming |
| 132 | +// note: v[0] it's allocated, but maybe not used |
| 133 | +// read example: |
| 134 | +for (int i = 1; i <= n; ++i) { |
| 135 | + fin >> v[i]; |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +### matrix |
| 140 | +You should always use `std::vector<std::vector<T>>`. |
| 141 | + |
| 142 | +```cpp |
| 143 | +// most common usage at PA it's 1-indexed matrix for DP |
| 144 | +// n x m matrix filled with zeros |
| 145 | +std::vector<std::vector<int>> dp{n + 1, std::vector<int>{m + 1, 0}}; |
| 146 | +// use: |
| 147 | +// dp[1][1], dp[1][2], ..., dp[1][m] |
| 148 | +// ... |
| 149 | +// dp[n][1], dp[n][2], ..., dp[n][m] |
| 150 | +// note: row 0 and column 0 are not used! |
| 151 | +// traversal example: |
| 152 | +for (int i = 1; i <= n; ++i) { |
| 153 | + for (int j = 1; j <= m; ++j) { |
| 154 | + // do something with dp[i][j] |
| 155 | + } |
| 156 | +} |
| 157 | +``` |
| 158 | + |
| 159 | +### stack |
| 160 | +You should always use `std::stack<T>`. |
| 161 | + |
| 162 | +```cpp |
| 163 | +std::stack<int> st; |
| 164 | +st.push(1); |
| 165 | +st.push(2); |
| 166 | +st.push(3); |
| 167 | + |
| 168 | +while (!st.empty()) { |
| 169 | + auto top = st.top(); |
| 170 | + st.pop(); |
| 171 | + std::cout << top << "\n"; |
| 172 | +} |
| 173 | +// print: 3 2 1 |
| 174 | +``` |
| 175 | + |
| 176 | +### hashtable |
| 177 | +You should always use `std::unordered_map<K, V>`. |
| 178 | + |
| 179 | +```cpp |
| 180 | +std::unordered_map<std::string, int> frequency; |
| 181 | +frequency["gigel"]++; |
| 182 | +frequency["gigel"]++; |
| 183 | +frequency["gigel"]++; |
| 184 | +frequency["gigel"]++; |
| 185 | +frequency["gigel"]++; |
| 186 | +frequency["not_gigel"]++; |
| 187 | + |
| 188 | +for (auto& [name, count] : frequency) { |
| 189 | + std::cout << name << " " << count << "\n"; |
| 190 | +} |
| 191 | +// possible output (because it's unordered): |
| 192 | +// not_gigel 1 |
| 193 | +// gigel 5 |
| 194 | +// |
| 195 | +// if using `std::map` the output is guaranteed to be (sorted keys): |
| 196 | +// gigel 5 |
| 197 | +// not_gigel 1 |
| 198 | +``` |
| 199 | + |
| 200 | +### set |
| 201 | + |
| 202 | +#### ordered set |
| 203 | +You should always use `std::set<T>` (ascending element order) or `std::set<T, std::greater<T>>` (descending element ordere). |
| 204 | + |
| 205 | +#### unordered set |
| 206 | +You should always use `std::unordered_set<T>`. |
| 207 | + |
| 208 | +#### example |
| 209 | +```cpp |
| 210 | +std::set<int> s; |
| 211 | +s.insert(1); |
| 212 | +s.insert(12); |
| 213 | +s.insert(12); |
| 214 | +s.insert(6); |
| 215 | +s.insert(6); |
| 216 | +s.insert(1); |
| 217 | + |
| 218 | +for (auto x : s) { |
| 219 | + std::cout << s << "\n"; |
| 220 | +} |
| 221 | +// print: 1 6 12 |
| 222 | +``` |
| 223 | + |
| 224 | +### minheap |
| 225 | +You should always use `std::multiset<T>`. |
| 226 | + |
| 227 | +```cpp |
| 228 | +std::multiset<int> minheap; |
| 229 | +minheap.insert(1); |
| 230 | +minheap.insert(12); |
| 231 | +minheap.insert(6); |
| 232 | +minheap.insert(1); |
| 233 | + |
| 234 | +while (!minheap.empty()) { |
| 235 | + auto top = *minheap.begin(); |
| 236 | + minheap.erase(minheap.begin()); |
| 237 | + std::cout << top << "\n"; |
| 238 | +} |
| 239 | +// print: 1 1 6 12 |
| 240 | +``` |
| 241 | + |
| 242 | +### maxheap |
| 243 | +You should always use `std::multiset<T, std::greater<T>>`. |
| 244 | + |
| 245 | +```cpp |
| 246 | +std::multiset<int> maxheap; |
| 247 | +maxheap.insert(1); |
| 248 | +maxheap.insert(12); |
| 249 | +maxheap.insert(6); |
| 250 | +maxheap.insert(1); |
| 251 | + |
| 252 | +while (!minhmaxheapeap.empty()) { |
| 253 | + auto top = *maxheap.begin(); |
| 254 | + minheamaxheapp.erase(maxheap.begin()); |
| 255 | + std::cout << top << "\n"; |
| 256 | +} |
| 257 | +// print: 12 6 1 1 |
| 258 | +``` |
0 commit comments