#include <cstring>
#include <chrono>
#include <map>
#include <string>
#include <vector>
#include <unordered_map>
#include <iostream>
enum class animal
{
Unknown,
Aardvark,
Albatross,
Alligator,
Alpaca,
AmericanBison,
Ant,
Anteater,
Antelope,
Ape,
Armadillo,
};
animal to_animal_naive(const char* s)
{
if (std::strcmp(s, "Aardvark") == 0)
return animal::Aardvark;
if (std::strcmp(s, "Albatross") == 0)
return animal::Albatross;
if (std::strcmp(s, "Alligator") == 0)
return animal::Alligator;
if (std::strcmp(s, "Alpaca") == 0)
return animal::Alpaca;
if (std::strcmp(s, "AmericanBison") == 0)
return animal::AmericanBison;
if (std::strcmp(s, "Ant") == 0)
return animal::Ant;
if (std::strcmp(s, "Anteater") == 0)
return animal::Anteater;
if (std::strcmp(s, "Antelope") == 0)
return animal::Antelope;
if (std::strcmp(s, "Ape") == 0)
return animal::Ape;
if (std::strcmp(s, "Armadillo") == 0)
return animal::Armadillo;
return animal::Unknown;
}
animal to_animal_naive_map(const char* s)
{
struct animal_selector
{
std::map<std::string, animal> animal_map_;
animal_selector()
{
animal_map_["Aardvark"] = animal::Aardvark;
animal_map_["Albatross"] = animal::Albatross;
animal_map_["Alligator"] = animal::Alligator;
animal_map_["Alpaca"] = animal::Alpaca;
animal_map_["AmericanBison"] = animal::AmericanBison;
animal_map_["Ant"] = animal::Ant;
animal_map_["Anteater"] = animal::Anteater;
animal_map_["Antelope"] = animal::Antelope;
animal_map_["Ape"] = animal::Ape;
animal_map_["Armadillo"] = animal::Armadillo;
}
animal operator () (const char* s) const
{
auto found = animal_map_.find(s);
if (found != animal_map_.end())
return found->second;
return animal::Unknown;
}
};
static animal_selector selector;
return selector(s);
}
animal to_animal_map(const char* s)
{
struct animal_selector
{
struct compare
{
bool operator () (const char* s, const char* t) const
{
return std::strcmp(s, t) < 0;
}
};
std::map<const char*, animal, compare> animal_map_;
animal_selector()
{
animal_map_["Aardvark"] = animal::Aardvark;
animal_map_["Albatross"] = animal::Albatross;
animal_map_["Alligator"] = animal::Alligator;
animal_map_["Alpaca"] = animal::Alpaca;
animal_map_["AmericanBison"] = animal::AmericanBison;
animal_map_["Ant"] = animal::Ant;
animal_map_["Anteater"] = animal::Anteater;
animal_map_["Antelope"] = animal::Antelope;
animal_map_["Ape"] = animal::Ape;
animal_map_["Armadillo"] = animal::Armadillo;
}
animal operator () (const char* s) const
{
auto found = animal_map_.find(s);
if (found != animal_map_.end())
return found->second;
return animal::Unknown;
}
};
static animal_selector selector;
return selector(s);
}
animal to_animal_unordered_map(const char* s)
{
struct animal_selector
{
std::unordered_map<std::string, animal> animal_map_;
animal_selector()
{
animal_map_["Aardvark"] = animal::Aardvark;
animal_map_["Albatross"] = animal::Albatross;
animal_map_["Alligator"] = animal::Alligator;
animal_map_["Alpaca"] = animal::Alpaca;
animal_map_["AmericanBison"] = animal::AmericanBison;
animal_map_["Ant"] = animal::Ant;
animal_map_["Anteater"] = animal::Anteater;
animal_map_["Antelope"] = animal::Antelope;
animal_map_["Ape"] = animal::Ape;
animal_map_["Armadillo"] = animal::Armadillo;
}
animal operator () (const char* s) const
{
auto found = animal_map_.find(s);
if (found != animal_map_.end())
return found->second;
return animal::Unknown;
}
};
static animal_selector selector;
return selector(s);
}
template <animal A>
struct this_or_unknown
{
animal operator () (const char* s, const char* t) const
{
return std::strcmp(s, t) == 0 ? A : animal::Unknown;
}
};
animal to_animal_switch_only(const char* s)
{
switch (*s++)
{
default:
return animal::Unknown;
case 'A':
switch (*s++)
{
default:
return animal::Unknown;
case 'a':
return this_or_unknown<animal::Aardvark>()(s, "rdvark");
case 'l':
switch (*s++)
{
default:
return animal::Unknown;
case 'b':
return this_or_unknown<animal::Albatross>()(s, "atross");
case 'l':
return this_or_unknown<animal::Alligator>()(s, "igator");
case 'p':
return this_or_unknown<animal::Alpaca>()(s, "aca");
}
case 'm':
return this_or_unknown<animal::AmericanBison>()(s, "ericanBison");
case 'n':
switch (*s++)
{
default:
return animal::Unknown;
case 't':
switch (*s++)
{
default:
return animal::Unknown;
case '\0':
return animal::Ant;
case 'e':
switch (*s++)
{
default:
return animal::Unknown;
case 'a':
return this_or_unknown<animal::Anteater>()(s, "ter");
case 'l':
return this_or_unknown<animal::Antelope>()(s, "ope");
}
}
}
case 'p':
return *s == 'e' ? animal::Ape : animal::Unknown;
case 'r':
return this_or_unknown<animal::Armadillo>()(s, "madillo");
}
}
}
animal to_animal_if_only(const char* s)
{
if (*s++ == 'A')
{
if (*s == 'a')
{
return this_or_unknown<animal::Aardvark>()(++s, "rdvark");
}
else if (*s == 'l')
{
++s;
if (*s == 'b')
return this_or_unknown<animal::Albatross>()(++s, "atross");
else if (*s == 'l')
return this_or_unknown<animal::Alligator>()(++s, "igator");
else if (*s == 'p')
return this_or_unknown<animal::Alpaca>()(++s, "aca");
}
else if (*s == 'm')
{
return this_or_unknown<animal::AmericanBison>()(++s, "ericanBison");
}
else if (*s == 'n')
{
++s;
if (*s++ == 't')
{
if (*s == '\0')
{
return animal::Ant;
}
else if (*s++ == 'e')
{
if (*s == 'a')
return this_or_unknown<animal::Anteater>()(++s, "ter");
else if (*s == 'l')
return this_or_unknown<animal::Antelope>()(++s, "ope");
}
}
}
else if (*s == 'p' && *++s == 'e')
{
return animal::Ape;
}
else if (*s == 'r')
{
return this_or_unknown<animal::Armadillo>()(s, "madillo");
}
}
return animal::Unknown;
}
animal to_animal_nice_mix(const char* s)
{
if (*s++ == 'A')
{
switch (*s++)
{
default:
break;
case 'a':
return this_or_unknown<animal::Aardvark>()(s, "rdvark");
case 'l':
if (*s == 'b')
return this_or_unknown<animal::Albatross>()(++s, "atross");
else if (*s == 'l')
return this_or_unknown<animal::Alligator>()(++s, "igator");
else if (*s == 'p')
return this_or_unknown<animal::Alpaca>()(++s, "aca");
break;
case 'm':
return this_or_unknown<animal::AmericanBison>()(s, "ericanBison");
case 'n':
if (*s++ == 't')
{
if (*s == '\0')
{
return animal::Ant;
}
else if (*s++ == 'e')
{
if (*s == 'a')
return this_or_unknown<animal::Anteater>()(++s, "ter");
else if (*s == 'l')
return this_or_unknown<animal::Antelope>()(++s, "ope");
}
}
break;
case 'p':
return *s == 'e' ? animal::Ape : animal::Unknown;
case 'r':
return this_or_unknown<animal::Armadillo>()(s, "madillo");
}
}
return animal::Unknown;
}
template <typename Clock = std::chrono::high_resolution_clock>
class stopwatch
{
typename Clock::time_point last_;
public:
stopwatch()
: last_(Clock::now())
{}
void reset()
{
*this = stopwatch();
}
typename Clock::duration elapsed() const
{
return Clock::now() - last_;
}
typename Clock::duration tick()
{
auto now = Clock::now();
auto elapsed = now - last_;
last_ = now;
return elapsed;
}
};
template <typename T, typename Rep, typename Period>
T duration_cast(const std::chrono::duration<Rep, Period>& duration)
{
return duration.count() * static_cast<T>(Period::num) / static_cast<T>(Period::den);
}
int main()
{
//while (true)
//{
std::size_t max_iterations;
std::cout << "Max iterations: ";
std::cin >> max_iterations;
std::vector<std::string> animals;
std::cout << "Enter animals:\n";
for (std::string s;;)
{
std::cin >> s;
if (s == "start")
break;
animals.push_back(s);
}
stopwatch<> sw;
double t;
sw.reset();
for (auto i = max_iterations; i--; )
{
animal a = to_animal_naive(animals[i % animals.size()].c_str());
if (i % 13373 == 0 && a == animal::Albatross)
std::cout << '.';
}
std::cout << '\n';
t = duration_cast<double>(sw.elapsed());
std::cout << "to_animal_naive: " << t << '\n';
sw.reset();
for (auto i = max_iterations; i--; )
{
animal a = to_animal_naive_map(animals[i % animals.size()].c_str());
if (i % 13373 == 0 && a == animal::Albatross)
std::cout << '.';
}
std::cout << '\n';
t = duration_cast<double>(sw.elapsed());
std::cout << "to_animal_naive_map: " << t << '\n';
sw.reset();
for (auto i = max_iterations; i--; )
{
animal a = to_animal_map(animals[i % animals.size()].c_str());
if (i % 13373 == 0 && a == animal::Albatross)
std::cout << '.';
}
std::cout << '\n';
t = duration_cast<double>(sw.elapsed());
std::cout << "to_animal_map: " << t << '\n';
sw.reset();
for (auto i = max_iterations; i--; )
{
animal a = to_animal_unordered_map(animals[i % animals.size()].c_str());
if (i % 13373 == 0 && a == animal::Albatross)
std::cout << '.';
}
std::cout << '\n';
t = duration_cast<double>(sw.elapsed());
std::cout << "to_animal_unordered_map: " << t << '\n';
sw.reset();
for (auto i = max_iterations; i--; )
{
animal a = to_animal_switch_only(animals[i % animals.size()].c_str());
if (i % 13373 == 0 && a == animal::Albatross)
std::cout << '.';
}
std::cout << '\n';
t = duration_cast<double>(sw.elapsed());
std::cout << "to_animal_switch_only: " << t << '\n';
sw.reset();
for (auto i = max_iterations; i--; )
{
animal a = to_animal_if_only(animals[i % animals.size()].c_str());
if (i % 13373 == 0 && a == animal::Albatross)
std::cout << '.';
}
std::cout << '\n';
t = duration_cast<double>(sw.elapsed());
std::cout << "to_animal_if_only: " << t << '\n';
sw.reset();
for (auto i = max_iterations; i--; )
{
animal a = to_animal_nice_mix(animals[i % animals.size()].c_str());
if (i % 13373 == 0 && a == animal::Albatross)
std::cout << '.';
}
std::cout << '\n';
t = duration_cast<double>(sw.elapsed());
std::cout << "to_animal_nice_mix: " << t << '\n';
//}
}