 # The Amazing Race Leg Win / Last Place Simulator

Oct 31st, 2020
2,084
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. //Hydreigon_Lord
2. //The Amazing Race Leg Win / Last Place Simulation
3.
4. #include <iostream>
5. #include <string>
6. #include <vector>
7. #include <random>
8. #include <cmath>
9. #include <iomanip>
10. using namespace std;
11.
12. //Global constants
13. const long SIMULATIONS = 1000000;
14. const vector<string> TEAM_NAMES = {
15.     "Dave & Connor",
16.     "Pam & Winnie",
17.     "Max & Katie",
18.     "Caroline & Jennifer",
19.     "Joey & Meghan",
20.     "Mona & Beth",
21.     "Bates & Anthony",
22.     "Chuck & Wynona"
23. };
24. const vector<vector<int>> LEG_RANKS = {
25.     {3,2,1,1},
26.     {4,9,4,2},
27.     {9,8,8,3},
28.     {10,7,6,4},
29.     {6,4,5,5},
30.     {5,6,7,6},
31.     {2,1,3,7},
32.     {7,5,9,8}
33. };
34.
35. //Class to represent teams
36. class Team
37. {
38. public:
39.     //Creates a team with a blank name
40.     Team()
41.     {
42.         name = "";
43.     }
44.
45.     //Sets the team's name to the given name
46.     void setName(string n)
47.     {
48.         name = n;
49.     }
50.
51.     //Adds a leg rank to this team's rank progression
53.     {
54.         ranks.push_back(r);
55.     }
56.
57.     //Returns this team's name
58.     string getName() const
59.     {
60.         return name;
61.     }
62.
63.     //Returns the number of legs this team has competed in
64.     int numLegs() const
65.     {
66.         return (int)ranks.size();
67.     }
68.
69.     //Returns this team's last leg rank
70.     int lastRank() const
71.     {
72.         return ranks[ranks.size() - 1];
73.     }
74.
75.     //Returns this team's racing average (average leg rank)
76.     //Returns -1 if this team has no leg ranks
77.     double racingAverage() const
78.     {
79.         if (ranks.size() == 0)
80.             return -1;
81.         double sum = 0;
82.         for (int r: ranks) {
83.             sum += r;
84.         }
85.         return sum / ranks.size();
86.     }
87.
88.     //Returns this team's standard deviation of leg ranks
89.     //Returns -1 if this team has fewer than 2 leg ranks
90.     double sdLegRanks() const
91.     {
92.         if (ranks.size() < 2)
93.             return -1;
94.         double mean = racingAverage();
95.         double var = 0;
96.         for (int r: ranks) {
97.             var += pow(r - mean, 2);
98.         }
99.         return sqrt(var / (ranks.size() - 1));
100.     }
101.
102.     //Returns this team's volatility (average leg rank change)
103.     //Returns -1 if this team has fewer than 2 leg ranks
104.     double volatility() const
105.     {
106.         if (ranks.size() < 2)
107.             return -1;
108.         double sum = 0;
109.         int lastRank = ranks;
110.         for (int i = 1; i < ranks.size(); i++) {
111.             sum += abs(ranks[i] - lastRank);
112.             lastRank = ranks[i];
113.         }
114.         return sum / (ranks.size() - 1);
115.     }
116.
117.     //Returns this team's standard deviation of leg rank changes
118.     //Returns -1 if this team has fewer than 3 leg ranks
119.     double sdLegRankChanges() const
120.     {
121.         if (ranks.size() < 3)
122.             return -1;
123.         double mean = volatility();
124.         double var = 0;
125.         int lastRank = ranks;
126.         for (int i = 1; i < ranks.size(); i++) {
127.             var += pow(abs(ranks[i] - lastRank) - mean, 2);
128.             lastRank = ranks[i];
129.         }
130.         return sqrt(var / (ranks.size() - 2));
131.     }
132.
133.     //Converts this team to a string (equivalent to getName())
134.     operator string() const
135.     {
136.         return name;
137.     }
138.
139. private:
140.     string name;
141.     vector<int> ranks;
142.
143. };
144.
145. int main()
146. {
147.     if (TEAM_NAMES.size() != LEG_RANKS.size()) {
148.         cout << "The list of team names is length " << TEAM_NAMES.size();
149.         cout << ", but the list of leg ranks includes leg rank lists for " << LEG_RANKS.size() << " teams.\n";
150.         exit(1);
151.     }
152.
153.     //Seed the random engine
154.     random_device rd;
155.     seed_seq seq{rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()};
156.     mt19937_64 en(seq);
157.
158.     //Initialize the list of teams
159.     int n = (int)TEAM_NAMES.size();  //This will hold the number of teams in the simulation
160.     Team* teams = new Team[n];  //This is the master copy of the team list
161.     for (int i = 0; i < n; i++) {
162.         teams[i].setName(TEAM_NAMES[i]);
163.         for (int r: LEG_RANKS[i]) {
165.         }
166.     }
167.
168.     //Prepare for the simulations
169.     Team* tempTeams;  //This is a pointer to a team list for a particular simulation only
170.     vector<long> numWins, numLasts;
171.     vector<int> currRanks;
172.     for (int i = 0; i < n; i++) {
173.         numWins.push_back(0);
174.         numLasts.push_back(0);
175.         currRanks.push_back(teams[i].lastRank());
176.     }
177.     vector<double> results;
178.     uniform_int_distribution<int> randLegRanks(1, n);
179.     normal_distribution<double> randGaussian(0, 1);
180.
181.     //Perform the simulations
182.     long print_interval = 10000 / n;  //After every print_interval sims, print the current progress
183.     for (long s = 1; s <= SIMULATIONS; s++) {
184.         //Initialize the temporary teams list
185.         tempTeams = new Team[n];
186.         for (int i = 0; i < n; i++) {
187.             tempTeams[i] = teams[i];
188.             //Assign the team 3 additional random leg ranks
189.             for (int j = 0; j < 3; j++) {
191.             }
192.         }
193.
194.         //Generate the simulation results using one of two methods
195.         if (s % 2 == 0) {  //Simulate based on racing average and SD of leg ranks
196.             for (int i = 0; i < n; i++) {
197.                 results.push_back(tempTeams[i].racingAverage() + tempTeams[i].sdLegRanks() * randGaussian(en));
198.             }
199.         } else {  //Simulate based on current rank, volatility, and SD of leg rank changes
200.             for (int i = 0; i < n; i++) {
201.                 results.push_back(currRanks[i] + (generate_canonical<float, 32>(en) < 0.5 ? -1 : 1) * tempTeams[i].volatility() + tempTeams[i].sdLegRankChanges() * randGaussian(en));
202.             }
203.         }
204.
205.         //Determine who wins and who gets last place
206.         int winInd = 0, lastInd = 0;
207.         for (int i = 1; i < n; i++) {
208.             if (results[i] < results[winInd]) {
209.                 winInd = i;
210.             } else if (results[i] > results[lastInd]) {
211.                 lastInd = i;
212.             }
213.         }
214.         numWins[winInd]++;
215.         numLasts[lastInd]++;
216.
217.         //Cleanup
218.         delete[] tempTeams;
219.         results.clear();
220.         if (s % print_interval == 0) {
221.             cout << "Completed " << s << " out of " << SIMULATIONS << " simulations (";
222.             cout << (100 * s / SIMULATIONS) << "% done)\n";
223.         }
224.     }
225.
226.     //Report the results
227.     cout << left << setprecision(4) << fixed << showpoint;
228.     cout << setw(8) << "Rank";
229.     cout << setw(24) << "Team Name";
230.     cout << setw(8) << "Win %";
231.     cout << setw(8) << "Last %";
232.     cout << setw(8) << "R.Avg.";
233.     cout << setw(8) << "(SD)";
234.     cout << setw(8) << "Vol.";
235.     cout << setw(8) << "(SD)";
236.     cout << endl << string(80, '-') << endl;
237.     for (int i = 0; i < n; i++) {
238.         cout << setw(8) << currRanks[i];
239.         cout << setw(24) << teams[i].getName();
240.         cout << setw(8) << 100.0 * numWins[i] / SIMULATIONS;
241.         cout << setw(8) << 100.0 * numLasts[i] / SIMULATIONS;
242.         cout << setw(8) << teams[i].racingAverage();
243.         int numLegs = teams[i].numLegs();
244.         if (numLegs >= 2) {
245.             cout << setw(8) << teams[i].sdLegRanks();
246.             cout << setw(8) << teams[i].volatility();
247.             if (numLegs >= 3) {
248.                 cout << setw(8) << teams[i].sdLegRankChanges();
249.             }
250.         }
251.         cout << endl;
252.     }
253.
254.     delete[] teams;
255.     return 0;
256. }
RAW Paste Data