diff --git a/puzzles/training/airport_routes.cpp b/puzzles/training/airport_routes.cpp index c59638d..b3a1f19 100644 --- a/puzzles/training/airport_routes.cpp +++ b/puzzles/training/airport_routes.cpp @@ -1,9 +1,6 @@ /* VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}" VIM: let b:cf5run="{OUT}" -VIM-: let b:cppflags=g:Iboost.g:Itbb -VIM-: let b:ldflags=g:Lboost.g:Ltbb -VIM-: let b:ldlibpath=g:Bboost.g:Btbb */ #include #include diff --git a/puzzles/training/median_stream.cpp b/puzzles/training/median_stream.cpp new file mode 100644 index 0000000..69b29d9 --- /dev/null +++ b/puzzles/training/median_stream.cpp @@ -0,0 +1,159 @@ +/* +VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}" +VIM: let b:cf5run="{OUT}" +VIM-: let b:cppflags=g:Iboost.g:Itbb +VIM-: let b:ldflags=g:Lboost.g:Ltbb +VIM-: let b:ldlibpath=g:Bboost.g:Btbb +*/ +#include +#include +#include +#include +#include + +/* +Median Stream + You're given a list of n integers arr[0..(n-1)]. You must compute a list + output[0..(n-1)] such that, for each index i (between 0 and n-1, inclusive), + output[i] is equal to the median of the elements arr[0..i] (rounded down to + the nearest integer). + + The median of a list of integers is defined as follows. If the integers were + to be sorted, then: + + If there are an odd number of integers, then the median is equal to the + middle integer in the sorted order. + Otherwise, if there are an even number of integers, then the median is equal + to the average of the two middle-most integers in the sorted order. + +Input + n is in the range [1, 1,000,000]. + Each value arr[i] is in the range [1, 1,000,000]. +Output + Return a list of n integers output[0..(n-1)], as described above. + +Example 1 + n = 4 + arr = [5, 15, 1, 3] + output = [5, 10, 5, 4] + The median of [5] is 5, the median of [5, 15] is (5 + 15) / 2 = 10, + the median of [5, 15, 1] is 5, and the median of [5, 15, 1, 3] is (3 + 5) / 2 = 4. + +Example 2 + n = 2 + arr = [1, 2] + output = [1, 1] + The median of [1] is 1, + the median of [1, 2] is (1 + 2) / 2 = 1.5 (which should be rounded down to 1). +*/ + +std::vector findMedian(std::vector arr) { + // Write your code here + std::vector r; + std::vector l; + + for (size_t i = 0; i < arr.size(); ++i){ + l.push_back(arr[i]); + std::push_heap(l.begin(), l.end()); + + if (l.size() > ((i+1)/2+1)){ + std::pop_heap(l.begin(), l.end()); + l.resize(l.size()-1); + } + + if ((i+1)%2){ + r.push_back(l[0]); + } else if (l.size() == 2){ + r.push_back( (l[0]+l[1])/2 ); + } else { + r.push_back( (l[0]+std::max(l[1],l[2]))/2 ); + } + } + return r; +} + + +// These are the tests we use to determine if the solution is correct. +// You can add your own at the bottom, but they are otherwise not editable! +void printIntegerVector(std::vector array) { + int size = array.size(); + std::cout << "["; + for (int i = 0; i < size; i++) { + if (i != 0) { + std::cout << ", "; + } + std::cout << array[i]; + } + std::cout << "]"; +} + +int test_case_number = 1; + +void check(std::vector & expected, std::vector & output) { + int expected_size = expected.size(); + int output_size = output.size(); + bool result = true; + if (expected_size != output_size) { + result = false; + } + for (int i = 0; i < std::min(expected_size, output_size); i++) { + result &= (output[i] == expected[i]); + } + const char* rightTick = "PASS - "; + const char* wrongTick = "FAIL - "; + if (result) { + std::cout << rightTick << "Test #" << test_case_number << "\n"; + } + else { + std::cout << wrongTick << "Test #" << test_case_number << ": Expected "; + printIntegerVector(expected); + std::cout << " Your output: "; + printIntegerVector(output); + std::cout << std::endl; + } + test_case_number++; +} + +int main ( void ) +{try{ + auto begin = std::chrono::high_resolution_clock::now(); + + { + std::vector arr_1{5, 15, 1, 3}; + std::vector expected_1{5, 10, 5, 4}; + std::vector output_1 = findMedian(arr_1); + check(expected_1, output_1); + }{ + std::vector arr_2{2, 4, 7, 1, 5, 3}; + std::vector expected_2{2, 3, 4, 3, 4, 3}; + std::vector output_2 = findMedian(arr_2); + check(expected_2, output_2); + }{ + std::vector arr_2{2, 4, 7, 1, 5}; + std::vector expected_2{2, 3, 4, 3, 4}; + std::vector output_2 = findMedian(arr_2); + check(expected_2, output_2); + }{ + std::vector arr_2{2, 4, 7, 1, 5, 3, 4}; + std::vector expected_2{2, 3, 4, 3, 4, 3, 4 }; + std::vector output_2 = findMedian(arr_2); + check(expected_2, output_2); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration seconds = end - begin; + std::cout << "Time: " << seconds.count() << std::endl; + return 0; +} +catch ( const std::exception& e ) +{ + std::cerr << std::endl + << "std::exception(\"" << e.what() << "\")." << std::endl; + return 2; +} +catch ( ... ) +{ + std::cerr << std::endl + << "unknown exception." << std::endl; + return 1; +}}