Skip to content

Commit 6371d74

Browse files
authored
add tutorial/cpp/tldr (acs-pa#6)
1 parent 4a50a5f commit 6371d74

File tree

1 file changed

+258
-0
lines changed

1 file changed

+258
-0
lines changed

tutorial/cpp/tldr.md

+258
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
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

Comments
 (0)