Created
January 20, 2019 04:28
-
-
Save Xirema/f81e28106080f8ebfac6fcb7f206190c to your computer and use it in GitHub Desktop.
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<Probability/BasicRolls.h> | |
#include<vector> | |
#include<unordered_set> | |
#include<map> | |
#include<unordered_map> | |
#include<iostream> | |
#include<string> | |
#include<chrono> | |
#include<numeric> | |
#include<fstream> | |
#include<experimental/unordered_set> | |
enum CardType { | |
FATES, VIZIER, COMET, GEM, JESTER, KEY, KNIGHT, MOON, STAR, SUN, BALANCE, THRONE, RUIN, FOOL, FLAMES, ROGUE, DONJON, EURYALE, IDIOT, TALONS, SKULL, VOID | |
}; | |
enum Value { | |
GOOD, BAD, NEUTRAL | |
}; | |
struct Card { | |
CardType type; | |
Card(CardType type) : type(type) { | |
} | |
std::string getName() const { | |
switch (type) { | |
case FATES: return "Fates"; | |
case VIZIER: return "Vizier"; | |
case COMET: return "Comet"; | |
case GEM: return "Gem"; | |
case JESTER: return "Jester"; | |
case KEY: return "Key"; | |
case KNIGHT: return "Knight"; | |
case MOON: return "Moon"; | |
case STAR: return "Star"; | |
case SUN: return "Sun"; | |
case BALANCE: return "Balance"; | |
case THRONE: return "Throne"; | |
case RUIN: return "Ruin"; | |
case FOOL: return "Fool"; | |
case FLAMES: return "Flames"; | |
case ROGUE: return "Rogue"; | |
case DONJON: return "Donjon"; | |
case EURYALE: return "Euryale"; | |
case IDIOT: return "Idiot"; | |
case TALONS: return "Talons"; | |
case SKULL: return "Skull"; | |
case VOID: return "Void"; | |
default: throw std::runtime_error("Unnamed CardType enum!"); | |
} | |
} | |
template<typename SET> | |
Value getValue(SET const& types) const { | |
switch (type) { | |
case FATES: | |
case VIZIER: | |
case COMET: | |
case GEM: | |
case JESTER: | |
case KEY: | |
case KNIGHT: | |
case MOON: | |
case STAR: | |
case SUN: | |
return GOOD; | |
case BALANCE: | |
case THRONE: | |
case RUIN: | |
case FLAMES: | |
case FOOL: | |
return NEUTRAL; | |
case DONJON: | |
case EURYALE: | |
case IDIOT: | |
case SKULL: | |
case VOID: | |
return BAD; | |
case TALONS: | |
if (types.count(MOON) || types.count(FATES)) | |
return GOOD; | |
else | |
return BAD; | |
case ROGUE: | |
if (types.count(MOON)) | |
return NEUTRAL; | |
else | |
return BAD; | |
default: | |
throw std::runtime_error("We didn't cover " + getName() + "!"); | |
} | |
} | |
friend bool operator==(Card const& a, Card const& b) { | |
return a.type == b.type; | |
} | |
uint64_t hashCode() { | |
std::hash<CardType> hasher; | |
return hasher(type); | |
} | |
}; | |
int main() { | |
using probability::cpp_rational; | |
using namespace std::chrono_literals; | |
const std::unordered_set<CardType> types{ | |
FATES, VIZIER, COMET, GEM, JESTER, KEY, KNIGHT, MOON, STAR, SUN, BALANCE, THRONE, RUIN, FOOL, FLAMES, ROGUE, DONJON, EURYALE, IDIOT, TALONS, SKULL, VOID | |
}; | |
std::unordered_map<std::set<CardType>, cpp_rational> results; | |
std::map<std::pair<size_t, size_t>, cpp_rational> goodResults; | |
std::map<std::pair<size_t, size_t>, cpp_rational> goodOrNeutralResults; | |
for (CardType type : types) | |
results[{type}] = cpp_rational(1) / types.size(); | |
std::set<CardType> stoppers{ TALONS, SKULL, VOID }; | |
auto period = 500ms; | |
auto lastUpdate = std::chrono::steady_clock::now() - period; | |
bool done = false; | |
while (!done) { | |
auto now = std::chrono::steady_clock::now(); | |
if (now - lastUpdate > period) { | |
lastUpdate += period; | |
std::cerr << "Num of Results: " << results.size() << std::endl; | |
std::cerr << "Num of Final Results: " << goodResults.size() << std::endl; | |
std::cerr << "Num of Final Results: " << goodOrNeutralResults.size() << std::endl; | |
} | |
std::unordered_map<std::set<CardType>, cpp_rational> newResults; | |
done = true; | |
for (auto const& pair : results) { | |
auto const& set = pair.first; | |
if (std::none_of(stoppers.begin(), stoppers.end(), [&set](CardType type) {return set.count(type) != 0; })) { | |
done = false; | |
std::unordered_set<CardType> availableCards = types; | |
std::experimental::erase_if(availableCards, [&set](CardType type) {return set.count(type) != 0; }); | |
for (CardType type : availableCards) { | |
std::set<CardType> newSet = set; | |
newSet.insert(type); | |
newResults[newSet] += results[set] / availableCards.size(); | |
} | |
} | |
else { | |
size_t goodCount = std::accumulate(set.begin(), set.end(), 0ull, [&set](size_t num, CardType type) {Value value = Card(type).getValue(set); return num + (value == GOOD ? 1 : 0); }); | |
size_t goodOrNeutralCount = std::accumulate(set.begin(), set.end(), 0ull, [&set](size_t num, CardType type) {Value value = Card(type).getValue(set); return num + (value != BAD ? 1 : 0); }); | |
std::pair<size_t, size_t> goodRun{ goodCount, set.size() }; | |
std::pair<size_t, size_t> neutralRun{ goodOrNeutralCount, set.size() }; | |
goodResults[goodRun] += results[set]; | |
goodOrNeutralResults[neutralRun] += results[set]; | |
} | |
} | |
results = newResults; | |
} | |
std::ofstream out("results.txt"); | |
out << "Good Results:" << std::endl; | |
cpp_rational total = 0; | |
cpp_rational goodTotal = 0; | |
cpp_rational neutralTotal = 0; | |
for (auto const& [run, result] : goodResults) { | |
if (run.first > 0 && run.first - run.second == 0) | |
goodTotal += result; | |
out << run.first << ", " << run.second << ", " << result << ", " << result.convert_to<double>() << std::endl; | |
total += result; | |
} | |
out << "Good Or Neutral Results:" << std::endl; | |
for (auto const&[run, result] : goodOrNeutralResults) { | |
if (run.first > 0 && run.first - run.second == 0) | |
neutralTotal += result; | |
out << run.first << ", " << run.second << ", " << result << ", " << result.convert_to<double>() << std::endl; | |
} | |
out << "Total was " << total << std::endl; | |
out << "Good Total was " << goodTotal << std::endl; | |
out << "Neutral Total was " << neutralTotal << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment