Skip to content

Instantly share code, notes, and snippets.

@jymchng
Last active July 29, 2023 03:36
Show Gist options
  • Save jymchng/bf527d68a9a352cf43078cad124673ea to your computer and use it in GitHub Desktop.
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.
#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