Last active
July 29, 2023 03:36
-
-
Save jymchng/bf527d68a9a352cf43078cad124673ea to your computer and use it in GitHub Desktop.
Calculating median at compile time and writing a C++ function that returns different types.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <array> | |
#include <iostream> | |
#include <cassert> | |
#include <cstddef> | |
#include <typeinfo> | |
template <std::size_t N> | |
struct IsSizeEven : std::integral_constant<bool, (N % 2) == 0> | |
{ | |
static constexpr bool value = std::integral_constant<bool, (N % 2) == 0>::value; | |
constexpr bool get() const | |
{ | |
return (N % 2) == 0; | |
} | |
}; | |
template <std::size_t N> | |
constexpr bool is_size_even_v = IsSizeEven<N>::value; | |
template <typename... Args> | |
struct AllSameType : std::integral_constant<bool, true> | |
{ | |
static constexpr bool value = true; | |
constexpr bool get() const noexcept | |
{ | |
return value; | |
} | |
}; | |
template <typename Arg1, typename... Args> | |
struct AllSameType<Arg1, Args...> : std::conjunction<std::is_same<Arg1, Args>...> | |
{ | |
static constexpr bool value = std::conjunction<std::is_same<Arg1, Args>...>::value; | |
constexpr bool get() const noexcept | |
{ | |
return value; | |
} | |
}; | |
template <typename... _Args> | |
constexpr bool all_same_type_v = AllSameType<_Args...>::value; | |
template <typename... Args, typename = std::enable_if_t<all_same_type_v<Args...>>> | |
constexpr std::conditional_t<is_size_even_v<sizeof...(Args)>, float, int> | |
median(Args &&...args) | |
{ | |
std::array<int, sizeof...(Args)> sortedArr{std::forward<Args>(args)...}; | |
std::sort(sortedArr.begin(), sortedArr.end()); | |
constexpr int N = sizeof...(Args); | |
if constexpr (N == 0) | |
{ | |
return 0; | |
} | |
if constexpr (N % 2 == 0) | |
{ | |
float middle1 = sortedArr[N / 2 - 1]; | |
float middle2 = sortedArr[N / 2]; | |
return (middle1 + middle2) / 2; | |
} | |
else | |
{ | |
return sortedArr[N / 2]; | |
} | |
} | |
template <std::size_t N> | |
constexpr std::conditional_t<(N % 2) == 0, float, int> | |
median(const std::array<int, N> &arr) | |
{ | |
std::array<int, N> sortedArr = arr; | |
std::sort(sortedArr.begin(), sortedArr.end()); | |
if constexpr (N == 0) | |
{ | |
return 0; | |
} | |
if constexpr (N % 2 == 0) | |
{ | |
float middle1 = sortedArr[N / 2 - 1]; | |
float middle2 = sortedArr[N / 2]; | |
return (middle1 + middle2) / 2; | |
} | |
else | |
{ | |
return sortedArr[N / 2]; | |
} | |
} | |
int main() | |
{ | |
auto median_one = median(1, 2, 3, 4, 5); | |
auto median_two = median(1, 2, 3, 4, 5, 6); | |
auto median_three = median(42); | |
auto median_four = median(10, 20); | |
auto median_five = median(0); | |
auto median_six = median(); | |
// auto median_twelve = median(1, 2, 3, 3.5, 4, 5, 5.5, 6); compilation error intended | |
static_assert(std::is_same_v<decltype(median_one), int>); | |
static_assert(std::is_same_v<decltype(median_two), float>); | |
static_assert(std::is_same_v<decltype(median_three), int>); | |
static_assert(std::is_same_v<decltype(median_four), float>); | |
static_assert(std::is_same_v<decltype(median_five), int>); | |
static_assert(std::is_same_v<decltype(median_six), float>); | |
std::cout << " median_one " << median_one << std::endl; | |
std::cout << " median_two " << median_two << std::endl; | |
std::cout << " median_three " << median_three << std::endl; | |
std::cout << " median_four " << median_four << std::endl; | |
std::cout << " median_five " << median_five << std::endl; | |
std::cout << " median_six " << median_six << std::endl; | |
assert(median_one == 3); | |
assert(median_two == 3.5); | |
assert(median_three == 42); | |
assert(median_four == 15.0); | |
assert(median_five == 0); | |
assert(median_six == 0.0); | |
std::cout << "All test cases in Part One passed successfully!" << std::endl; | |
std::array<int, 5> arr1 = {1, 2, 3, 4, 5}; | |
std::array<int, 6> arr2 = {1, 2, 3, 4, 5, 6}; | |
std::array<int, 1> arr3 = {42}; | |
std::array<int, 2> arr4 = {10, 20}; | |
std::array<int, 0> arr6 = {}; // Empty array | |
auto median_seven = median<5>(arr1); | |
auto median_eight = median<6>(arr2); | |
auto median_nine = median<1>(arr3); | |
auto median_ten = median<2>(arr4); | |
auto median_eleven = median<0>(arr6); | |
static_assert(std::is_same_v<decltype(median_seven), int>); | |
static_assert(std::is_same_v<decltype(median_eight), float>); | |
static_assert(std::is_same_v<decltype(median_nine), int>); | |
static_assert(std::is_same_v<decltype(median_ten), float>); | |
static_assert(std::is_same_v<decltype(median_eleven), float>); | |
std::cout << " median_seven " << median_seven << std::endl; | |
std::cout << " median_eight " << median_eight << std::endl; | |
std::cout << " median_nine " << median_nine << std::endl; | |
std::cout << " median_ten " << median_ten << std::endl; | |
std::cout << " median_eleven " << median_eleven << std::endl; | |
assert(median_seven == 3); // Median of odd-sized array (5 elements) | |
assert(median_eight == 3.5); // Median of even-sized array (6 elements) | |
assert(median_nine == 42); | |
assert(median_ten == 15.0); | |
assert(median_eleven == 0); | |
std::array<int, 1000> largeArr; | |
for (int i = 0; i < 1000; ++i) | |
largeArr[i] = i; | |
auto largeArrmedian = median<1000>(largeArr); | |
assert(largeArrmedian == 499.5); | |
std::array<int, 999> largeOddArr; | |
for (int i = 0; i < 999; ++i) | |
largeOddArr[i] = i; | |
auto largeOddArrMedian = median<999>(largeOddArr); | |
assert(largeOddArrMedian == 499); | |
static_assert(std::is_same_v<decltype(largeArrmedian), float>); | |
static_assert(std::is_same_v<decltype(largeOddArrMedian), int>); | |
std::cout << " largeArrmedian " << largeArrmedian << std::endl; | |
std::cout << " largeOddArrMedian " << largeOddArrMedian << std::endl; | |
std::cout << "All test cases in Part Two passed successfully!" << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment