Skip to content

Instantly share code, notes, and snippets.

@Xirema
Created January 20, 2019 04:28
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 Xirema/f81e28106080f8ebfac6fcb7f206190c to your computer and use it in GitHub Desktop.
Save Xirema/f81e28106080f8ebfac6fcb7f206190c to your computer and use it in GitHub Desktop.
#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