Skip to content

Instantly share code, notes, and snippets.

@klmr
Created October 23, 2019 12:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klmr/b7f6b540ad04d291ccdb842b56b669e2 to your computer and use it in GitHub Desktop.
Save klmr/b7f6b540ad04d291ccdb842b56b669e2 to your computer and use it in GitHub Desktop.
Frequency table and mode calculation
#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