-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathminmax.cpp
More file actions
executable file
·181 lines (155 loc) · 5.69 KB
/
Copy pathminmax.cpp
File metadata and controls
executable file
·181 lines (155 loc) · 5.69 KB
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
// Answering a redditor's question to review
// his code
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <chrono>
#include <random>
using namespace std;
//if one element its max and min
//divide and conquer
struct values {
int max, min;
};
// counters to keep track of how much each function is called
int maxCallCount1 = 0;
int minCallCount1 = 0;
int minCallCount2 = 0;
int maxCallCount2 = 0;
int findCallCount1 = 0;
int findCallCount2 = 0;
// wrapper functions for std::min and std::max to
int customMax1(int a, int b) {
++maxCallCount1;
return std::max(a, b);
}
int customMin1(int a, int b) {
++minCallCount1;
return std::min(a, b);
}
int customMax2(int a, int b) {
++maxCallCount2;
return std::max(a, b);
}
int customMin2(int a, int b) {
++minCallCount2;
return std::min(a, b);
}
struct values findMinMax(vector<int> &a, int start, int end) {
++findCallCount1;
if (a.empty()) return values{0, 0};
if(start < end) {
int mid = (start + end) / 2;
//recursive calls on both halfs to get min, max values
struct values left_res = findMinMax(a, start, mid);
struct values right_res = findMinMax(a, mid+1, end);
//compare left and right values and set for min,
//max for entire length
struct values final_res;
final_res.min = customMin1(left_res.min, right_res.min);
final_res.max = customMax1(left_res.max, right_res.max);
return final_res;
} else {
//if only one value is there, then it is the both min,
//and max;
struct values final_res;
final_res.min = final_res.max = a[start];
return final_res;
}
}
// version of findMinMax with 2 exit condition
values findMinMax2(vector<int> &a, int start, int end) {
++findCallCount2;
if (a.empty()) return values{0, 0};
struct values final_res;
// if there's only two elements, directly compare them
if (end-start == 1) {
final_res.min = customMin2(a[start], a[end]);
final_res.max = customMax2(a[start], a[end]);
return final_res;
}
// if there's only one element, it's both max and min
else if (end == start) {
final_res.min = final_res.max = a[start];
return final_res;
}
// else you know the drill: divide and conquer
else {
int mid = (end + start) / 2;
struct values left_res = findMinMax2(a, start, mid);
struct values right_res = findMinMax2(a, mid+1, end);
struct values final_res;
final_res.min = customMin2(left_res.min, right_res.min);
final_res.max = customMax2(left_res.max, right_res.max);
return final_res;
}
}
// function to show that above way of finding min
// and max is terrible in practice
values findMinMax3(vector<int>& a) {
if (a.empty()) return values{0, 0};
int minimum = a[0];
int maximum = a[0];
for (int i = 0; i < a.size(); ++i) {
if (minimum > a[i]) minimum = a[i];
if (maximum < a[i]) maximum = a[i];
}
return values{ maximum, minimum };
}
int main() {
using namespace std::chrono;
high_resolution_clock clock;
const int sampleSize = 25000000;
// generate lots of random integers and put it into the vec
// clock.now() just a function to time the performance:
// can be safely ignored
vector<int> vec;
auto generateStart = clock.now();
generate_n(back_inserter(vec), sampleSize, rand);
auto generateEnd = clock.now();
auto oneStart = clock.now();
struct values res = findMinMax(vec, 0, vec.size()-1);
auto oneEnd = clock.now();
auto twoStart = clock.now();
struct values res2 = findMinMax2(vec, 0, vec.size()-1);
auto twoEnd = clock.now();
auto threeStart = clock.now();
struct values res3 = findMinMax3(vec);
auto threeEnd = clock.now();
cout << "Testing with " << sampleSize << " elements" << endl;
cout << "Generating random numbers took "
<< duration_cast<milliseconds>
(threeEnd-threeStart).count()
<< " ms" <<endl;
cout << "--------------------------------------------\n";
cout << "min : " << res.min << ", "
<< "max : " << res.max << endl;
cout << "min2 : " << res2.min << ", "
<< "max2 : " << res2.max << endl;
cout << "--------------------------------------------\n";
cout << "called min " << minCallCount1 << " times" << endl;
cout << "called max " << maxCallCount1 << " times" << endl;
cout << "--------------------------------------------\n";
cout << "called min2 " << minCallCount2 << " times" << endl;
cout << "called max2 " << maxCallCount2 << " times" << endl;
cout << "--------------------------------------------\n";
cout << "called findMinMax "
<< findCallCount1 << " times" << endl;
cout << "called findMinMax2 "
<< findCallCount2 << " times" << endl;
cout << "--------------------------------------------\n";
cout << "Time taken with findMinMax: "
<< duration_cast<milliseconds>(oneEnd-oneStart).count()
<< " ms" << endl;
cout << "--------------------------------------------\n";
cout << "Time taken with findMinMax2: "
<< duration_cast<milliseconds>(twoEnd-twoStart).count()
<< " ms" <<endl;
cout << "--------------------------------------------\n";
cout << "Time taken with findMinMax3: "
<< duration_cast<milliseconds>
(threeEnd-threeStart).count()
<< " ms" <<endl;
return 0;
}