Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Hydreigon_Lord
- //The Amazing Race Leg Win / Last Place Simulation
- #include <iostream>
- #include <string>
- #include <vector>
- #include <random>
- #include <cmath>
- #include <iomanip>
- using namespace std;
- //Global constants
- const long SIMULATIONS = 1000000;
- const vector<string> TEAM_NAMES = {
- "Dave & Connor",
- "Pam & Winnie",
- "Max & Katie",
- "Caroline & Jennifer",
- "Joey & Meghan",
- "Mona & Beth",
- "Bates & Anthony",
- "Chuck & Wynona"
- };
- const vector<vector<int>> LEG_RANKS = {
- {3,2,1,1},
- {4,9,4,2},
- {9,8,8,3},
- {10,7,6,4},
- {6,4,5,5},
- {5,6,7,6},
- {2,1,3,7},
- {7,5,9,8}
- };
- //Class to represent teams
- class Team
- {
- public:
- //Creates a team with a blank name
- Team()
- {
- name = "";
- }
- //Sets the team's name to the given name
- void setName(string n)
- {
- name = n;
- }
- //Adds a leg rank to this team's rank progression
- void addRank(int r)
- {
- ranks.push_back(r);
- }
- //Returns this team's name
- string getName() const
- {
- return name;
- }
- //Returns the number of legs this team has competed in
- int numLegs() const
- {
- return (int)ranks.size();
- }
- //Returns this team's last leg rank
- int lastRank() const
- {
- return ranks[ranks.size() - 1];
- }
- //Returns this team's racing average (average leg rank)
- //Returns -1 if this team has no leg ranks
- double racingAverage() const
- {
- if (ranks.size() == 0)
- return -1;
- double sum = 0;
- for (int r: ranks) {
- sum += r;
- }
- return sum / ranks.size();
- }
- //Returns this team's standard deviation of leg ranks
- //Returns -1 if this team has fewer than 2 leg ranks
- double sdLegRanks() const
- {
- if (ranks.size() < 2)
- return -1;
- double mean = racingAverage();
- double var = 0;
- for (int r: ranks) {
- var += pow(r - mean, 2);
- }
- return sqrt(var / (ranks.size() - 1));
- }
- //Returns this team's volatility (average leg rank change)
- //Returns -1 if this team has fewer than 2 leg ranks
- double volatility() const
- {
- if (ranks.size() < 2)
- return -1;
- double sum = 0;
- int lastRank = ranks[0];
- for (int i = 1; i < ranks.size(); i++) {
- sum += abs(ranks[i] - lastRank);
- lastRank = ranks[i];
- }
- return sum / (ranks.size() - 1);
- }
- //Returns this team's standard deviation of leg rank changes
- //Returns -1 if this team has fewer than 3 leg ranks
- double sdLegRankChanges() const
- {
- if (ranks.size() < 3)
- return -1;
- double mean = volatility();
- double var = 0;
- int lastRank = ranks[0];
- for (int i = 1; i < ranks.size(); i++) {
- var += pow(abs(ranks[i] - lastRank) - mean, 2);
- lastRank = ranks[i];
- }
- return sqrt(var / (ranks.size() - 2));
- }
- //Converts this team to a string (equivalent to getName())
- operator string() const
- {
- return name;
- }
- private:
- string name;
- vector<int> ranks;
- };
- int main()
- {
- if (TEAM_NAMES.size() != LEG_RANKS.size()) {
- cout << "The list of team names is length " << TEAM_NAMES.size();
- cout << ", but the list of leg ranks includes leg rank lists for " << LEG_RANKS.size() << " teams.\n";
- exit(1);
- }
- //Seed the random engine
- random_device rd;
- seed_seq seq{rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()};
- mt19937_64 en(seq);
- //Initialize the list of teams
- int n = (int)TEAM_NAMES.size(); //This will hold the number of teams in the simulation
- Team* teams = new Team[n]; //This is the master copy of the team list
- for (int i = 0; i < n; i++) {
- teams[i].setName(TEAM_NAMES[i]);
- for (int r: LEG_RANKS[i]) {
- teams[i].addRank(r);
- }
- }
- //Prepare for the simulations
- Team* tempTeams; //This is a pointer to a team list for a particular simulation only
- vector<long> numWins, numLasts;
- vector<int> currRanks;
- for (int i = 0; i < n; i++) {
- numWins.push_back(0);
- numLasts.push_back(0);
- currRanks.push_back(teams[i].lastRank());
- }
- vector<double> results;
- uniform_int_distribution<int> randLegRanks(1, n);
- normal_distribution<double> randGaussian(0, 1);
- //Perform the simulations
- long print_interval = 10000 / n; //After every print_interval sims, print the current progress
- for (long s = 1; s <= SIMULATIONS; s++) {
- //Initialize the temporary teams list
- tempTeams = new Team[n];
- for (int i = 0; i < n; i++) {
- tempTeams[i] = teams[i];
- //Assign the team 3 additional random leg ranks
- for (int j = 0; j < 3; j++) {
- tempTeams[i].addRank(randLegRanks(en));
- }
- }
- //Generate the simulation results using one of two methods
- if (s % 2 == 0) { //Simulate based on racing average and SD of leg ranks
- for (int i = 0; i < n; i++) {
- results.push_back(tempTeams[i].racingAverage() + tempTeams[i].sdLegRanks() * randGaussian(en));
- }
- } else { //Simulate based on current rank, volatility, and SD of leg rank changes
- for (int i = 0; i < n; i++) {
- results.push_back(currRanks[i] + (generate_canonical<float, 32>(en) < 0.5 ? -1 : 1) * tempTeams[i].volatility() + tempTeams[i].sdLegRankChanges() * randGaussian(en));
- }
- }
- //Determine who wins and who gets last place
- int winInd = 0, lastInd = 0;
- for (int i = 1; i < n; i++) {
- if (results[i] < results[winInd]) {
- winInd = i;
- } else if (results[i] > results[lastInd]) {
- lastInd = i;
- }
- }
- numWins[winInd]++;
- numLasts[lastInd]++;
- //Cleanup
- delete[] tempTeams;
- results.clear();
- if (s % print_interval == 0) {
- cout << "Completed " << s << " out of " << SIMULATIONS << " simulations (";
- cout << (100 * s / SIMULATIONS) << "% done)\n";
- }
- }
- //Report the results
- cout << left << setprecision(4) << fixed << showpoint;
- cout << setw(8) << "Rank";
- cout << setw(24) << "Team Name";
- cout << setw(8) << "Win %";
- cout << setw(8) << "Last %";
- cout << setw(8) << "R.Avg.";
- cout << setw(8) << "(SD)";
- cout << setw(8) << "Vol.";
- cout << setw(8) << "(SD)";
- cout << endl << string(80, '-') << endl;
- for (int i = 0; i < n; i++) {
- cout << setw(8) << currRanks[i];
- cout << setw(24) << teams[i].getName();
- cout << setw(8) << 100.0 * numWins[i] / SIMULATIONS;
- cout << setw(8) << 100.0 * numLasts[i] / SIMULATIONS;
- cout << setw(8) << teams[i].racingAverage();
- int numLegs = teams[i].numLegs();
- if (numLegs >= 2) {
- cout << setw(8) << teams[i].sdLegRanks();
- cout << setw(8) << teams[i].volatility();
- if (numLegs >= 3) {
- cout << setw(8) << teams[i].sdLegRankChanges();
- }
- }
- cout << endl;
- }
- delete[] teams;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement