summaryrefslogtreecommitdiff
path: root/01-07.md
blob: 6e11fbb6644c2af32d5abb9668c10b406e2e2d7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
[\<- 01/05](01-05.md)

---

## Use Standard Library

```
#include <iostream>
```

- To use a function from `iostream`, need to specify the `std::___` namespace (since iostream belongs to the std namespace)
- To avoid having to write `std::` behind the `iostream` functions, you can write at the top `using namespace std;`
	- You can have multiple `using namespace` specifications
	- If a function name belongs to multiple namespaces that are called at the top (and each take the same number of parameters), this can lead to issues

---

## Preconditions and Postconditions

### Defining a Function

```
//example function definition for a function that squares an integer
int square(int A){
	return A*A;
}

int B = square(2); //B will equal 4
```

### Specifying Pre and Post conditions

- Preconditions - What must be true before calling your program/method
- Postconditions - What must be true/what will happen after your program returns

- For the above function:
	- Preconditions
		- None (it is implied that the input must be an integer)
	- Postconditions
		- If precondition is satisfied, postcondition must be true

### Examples

```
double get_sqrt(double A);
//preC  A >= 0 : input has to be a double and non-negative
//postC returns square root of integer
```

- What will happen if the user calls the following:

```
get_sqrt(-1);
```

- The program will not work, it may even crash!
	- Preconditions are important so that users know how to use the function without breaking it

```
void print_name(char *A);
//preC  input has to be an array of characters (and non-NULL)
//preC  array must be null-terminated ('\0' at the end)
//postC print the input to stdout with no spaces
```

### Assert

- the `assert()` function can be used to enforce preconditions
- Example:

```
double get_sqrt(double A){
	assert(A >= 0); //to enforce precondition

	//body of the program goes here
}
```

- Alternative example without using `assert()`

```
double get_sqrt(double A){
	if(A < 0){
		//print error message and exit
	}

	//body of the program goes here
}
```

- Detailed C++ Example

```
#include <iostream>
// uncomment to disable assert
// #define NDEBUG
#include <cassert>

int main(){
	assert(10 + 10 == 20);
	std::cout << "Execution continues past the first assert\n";

	assert(12+12 == 20);
	std::cout << "Execution continues past the second assert\n";
}
```

### Static Assert

- Static assert are all checked at compile time, rather than just whenever the program that the assert is called in is called
	- `static_assert(A > 0)`

- Detailed C++ Example

```
void foo(int *a){
	assert(a != NULL);
	std::cout << *a << std::endl;
}

void bar(int *a){
	static_assert(sizeof(a) == 8, "I can only compile on a 64-bit architecture!"); //to make sure the code is only compiled on a 64-bit architecture
}

int main(int argc, const char *argv[]){
	int *a = new int(4);
	foo(a);
	bar(a);

	return 0;
}
```

### Advantages of Using Preconditions and Postconditions

- Succinctly describes the behavior of a function without cluttering up your thinking with details of how the function works
- At a later point, you may reimplement the function in a new way but programs (which only depend on the precondition/postcondition) will still work with no changes.

---

## Time Analysis

### What is Time Analysis?

- How fast the system is running
- How fast the algorithm is executed
	- How many clock signals does it take
- Is it the algorithm's fault?

### Time Analysis?

- Time is a parameter that needs to be optimized!
	- Time is $
	- Some problems are interactable
	- Scalability
- Is it better to be faster?
	- YES! - time is money!
	- NO! - not always (for example, real time applications)

### How to do Time Analysis?

- Count the number of operations
- How??

```
int *add_array(int *array1, int *array2, int N){
	for(i = 0; i<N, i++){
		array1[i] += array2[i];
	}

	return array1;
}
```

- Number of operations depends on the input size

### Big-O Notation

- Declares the ORDER of the number of operations
- O(1), O(n), O(n^2)

### Various Big-O Notation

|Complexity|Function|Common name |
|----------|--------|------------|
|Highest   |n!      |factorial   |
|          |2^n     |exponential |
|          |n^d, d>3|polynomial  |
|          |n^3     |cubic       |
|          |n^2     |quadratic   |
|          |nsqrt(n)|            |
|          |nlog(n) |quasi-linear|
|          |n       |linear      | 
|          |sqrt(n) |root - n    | 
|          |log(n)  |logarithmic |
|Lowest    |1       |contsant    |

### Examples

|T(n)                |Complexity|
|--------------------|----------|
|5n^3 + 200n^2 + 15  |O(n^3)    |
|3n^2 + 2^300        |O(n^2)    |
|5log2(n) + 15ln(n)  |O(log(n)) |
|2log(n^3)           |O(log(n)) |
|4n + log(n)         |O(n)      |
|2^64                |O(1)      |
|log(n^10) + 2sqrt(n)|O(sqrt(n) |
|2^n + n^1000        |O(2^n)    |

### Big-O Comparisons

- Different ways to solve a problem -> different complexity

### Examples

```
for(i = 0; i<N; i++){
	statement;
}

O(N)
```

```
for(i = 0; i < N; i++){
	for(j = 0; j < N; j++){
		statement;
	}
}

O(N^2)
```

```
for(int i = 1; i <= n; ++i){
	for(int j = 1; j <= i; ++j){
		statement;
	}
}

O(?) (to be continued...)
```

### Best Case/Worst Case Scenario

```
bool search(vector<int> arr, int item){
	for(i = 0; i < arr.size; i++){
		if(arr[i] == item){
			return true;
		}
	}

	return false;
}

//if vector<int> arr{1, 2, 3, 4, 5}
search(arr, 1); //O(1) -> Best Case
search(arr, 5); //O(N) -> Worst Case
```

[01/12 ->](01-12.md)