Created
October 23, 2019 12:38
-
-
Save klmr/b7f6b540ad04d291ccdb842b56b669e2 to your computer and use it in GitHub Desktop.
Frequency table and mode calculation
This file contains 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 <initializer_list> | |
#include <iostream> | |
#include <iterator> | |
#include <string_view> | |
#include <type_traits> | |
#include <unordered_map> | |
namespace stats { | |
using std::begin, std::end; | |
template <typename K, typename V = std::size_t> | |
struct freq_table { | |
private: | |
std::unordered_map<K, V> counts; | |
template <typename C> | |
using NotSelf = std::enable_if_t<not std::is_same_v<std::remove_reference_t<C>, freq_table>>; | |
public: | |
using value_type = std::pair<K, V>; | |
template <typename I> | |
freq_table(I begin, I end) { | |
std::for_each(begin, end, [&](auto x) {counts[x] += 1;}); | |
} | |
template <typename C, typename = NotSelf<C>> // FIXME: NotSelf test necessary?! | |
explicit freq_table(C const& cont) : freq_table{begin(cont), end(cont)} {} | |
friend auto max(freq_table const& table) -> value_type { | |
return *std::max_element( | |
begin(table.counts), end(table.counts), | |
[](auto a, auto b) {return a.second < b.second;} | |
); | |
} | |
}; | |
namespace util { | |
template <typename T> | |
struct value_type { | |
using type = typename T::value_type; | |
}; | |
template <typename T, std::size_t N> | |
struct value_type<T[N]> { | |
using type = T; | |
}; | |
template <typename T> | |
using value_type_t = typename value_type<T>::type; | |
} // util | |
template <typename C> | |
auto count_all(C const& cont) { | |
return freq_table<util::value_type_t<C>>{cont}; | |
} | |
template <typename T> | |
auto count_all(std::initializer_list<T> cont) { | |
return freq_table<T>{cont}; | |
} | |
template <typename I> | |
auto mode(I begin, I end) { | |
using value_type = typename std::iterator_traits<I>::value_type; | |
return max(freq_table<value_type>{begin, end}).first; | |
} | |
template <typename C> | |
auto mode(C const& cont) { | |
using std::begin, std::end; | |
return mode(begin(cont), end(cont)); | |
} | |
template <typename T> | |
auto mode(std::initializer_list<T> cont) { | |
return mode(begin(cont), end(cont)); | |
} | |
} // stat | |
auto most_frequent_char(std::string_view str) -> char { | |
return stats::mode(str); | |
} | |
int main() { | |
std::cout << most_frequent_char("GATTACA") << "\n"; | |
std::cout << most_frequent_char("ABCDEFGHIJKLMNOPQRSTUVWXYZ") << "\n"; | |
std::cout << most_frequent_char("foobar") << "\n"; | |
std::cout << stats::mode({1, 2, 3, 3, 2, 1, 4, 2, 4}) << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment