I've decided to make a simple toy program: given a set of strings, count them with palindrome equivalence.
For instance, given { "abc", "123", "cba", "987" }
, the map should be { {"abc", 2}, {"123", 1"}, {"987", 1"} }
. I know that an unordered_map
has the constraint that if hash values between two keys are the same, so it must be that operator==
on the two mapped types should be true
. As far as I remember, it doesn't state that those values must be the same (for instance at bits level), correct me if I'm wrong.
So I've decided to make a custom class of palindrome strings that contain a hash, and a custom hasher. The hash returns the minimum hash value between string and its reverse.
The problem: AFAIK, the mapped class should have a default constructor, and of course, if I add it, it would be meaningless.
Can you help me in this (at my first sight) easy task? Here's my code, not working of course!
// Forget all these includes, this is a "scratch" file
#include <iostream>
#include <iterator>
#include <type_traits>
#include <string>
#include <utility>
#include <vector>
#include <tuple>
#include <typeinfo>
#include <utility>
#include <iomanip>
#include <unordered_map>
// Palindrome strings
class palindrome
{
public:
// Returns the minimum hash value between fwd and rev strings
static std::size_t hash(std::string s)
{
auto fun = std::hash<std::string>();
auto fwd = fun(s);
std::reverse(s.begin(), s.end());
auto rev = fun(s);
return fwd < rev ? fwd : rev;
}
// Default constructor
palindrome()
{
// <----- DAMN! Strings and hashes are useless!
}
// Constructor
palindrome(std::string s) : s_{s}
{
hash_ = palindrome::hash(s);
}
// Compare hashes only
bool operator==(const palindrome &r) const
{
return hash_ == r.hash_;
}
// The string
std::string s_;
// Hash and count
std::size_t hash_, count_;
};
// Custom hashing function
class palindrome_hash
{
public:
std::size_t operator()(const palindrome &key) const
{
return palindrome::hash(key.s_);
}
};
int main(int argc, const char * argv[])
{
// The map
std::unordered_map<std::string, palindrome, palindrome_hash> map;
// The strings
std::vector<std::string> v { "abc", "124", "cba", "987" };
// Count all strings with palindrome equivalence
for(const auto &p : v)
{
std::cout << "inserting " << p << std::endl;
map[p].count_++; // <----- DAMN!
}
std::cout << std::endl;
// Dump 'em!
for(const auto &p : map)
{
std::cout << p.first << " -> " << p.second.s_ << " , " << std::hex << p.second.hash_ << std::endl;
}
}
Aucun commentaire:
Enregistrer un commentaire