#include <iostream>
#include <inttypes.h>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <deque>
#include <cstring>
#include <cmath>
using namespace std;
#define CARDS_NUM 36
#define ITERATIONS 4096*128
// xxxxxxxx
// 76543210
// bits 1 and 0 - suit
// bits 5,4,3,2 - value
// 0000 - 6
// 0001 - 7
// 0010 - 8
// 0011 - 9
// 0100 - 10/A
// 0101 - jack B
// 0110 - queen C
// 0111 - king D
// 1000 - ace E
// 6 beats ace
inline uint8_t getval(const uint8_t card){
return (card >> 2) & 0x0F;
}
inline uint8_t getsuit(const uint8_t card){
return card & 0x3;
}
// <0 if c1 < c2
// 0 if c1 == c2
// >0 if c1 > c2
int8_t cmp(const uint8_t card1, const uint8_t card2){
uint8_t val1, val2;
val1 = getval(card1);
val2 = getval(card2);
if((val1 == 0) && (val2 == 8)){
return -1;
}
if((val1 == 8) && (val2 == 0)){
return 1;
}
return val1 - val2;
}
unsigned play(bool& winner){ //returns number of moves
vector<uint8_t> cards;
deque<uint8_t> player[2], add_deque;
for(int i = 0; i < CARDS_NUM; i++){
cards.push_back(i);
}
for(int i = 0; cards.size() != 1; i++){
int newcardnum = lrand48() % cards.size();
player[i % 2].push_back(cards[newcardnum]);
cards.erase(cards.begin()+newcardnum);
}
player[1].push_back(cards[0]);
cards.erase(cards.begin());
unsigned moves = 0;
while(!(player[0].empty() || player[1].empty() )){
moves++;
int card1 = player[0].front();
int card2 = player[1].front();
int res = cmp(card1, card2);
player[0].pop_front();
player[1].pop_front();
if(res == 0){
if(lrand48()%2){
add_deque.push_back(card1);
add_deque.push_back(card2);
}
else{
add_deque.push_back(card2);
add_deque.push_back(card1);
}
continue;
}
if(res < 0){
while(!add_deque.empty()){
player[1].push_back(add_deque.front());
add_deque.pop_front();
}
if(lrand48()%2){
player[1].push_back(card1);
player[1].push_back(card2);
}
else{
player[1].push_back(card2);
player[1].push_back(card1);
}
}
if(res > 0){
while(!add_deque.empty()){
player[0].push_back(add_deque.front());
add_deque.pop_front();
}
if(lrand48()%2){
player[0].push_back(card1);
player[0].push_back(card2);
}
else{
player[0].push_back(card2);
player[0].push_back(card1);
}
}
}
winner = player[0].empty();
return moves;
}
long double stats(const vector<unsigned> results, const vector<bool> winners, long double& winner, long double& stdev){
long double mean = 0;
winner = stdev = 0;
int total = results.size();
for(int i = 0; i < total; i++){
mean += ((long double)results[i]) / ((long double)total);
winner += ((long double)winners[i]) / ((long double)total);
}
for(int i = 0; i < total; i++){
stdev += pow(mean - (long double)results[i],2) / ((long double)total);
}
stdev = sqrt(stdev);
return mean;
}
int main(int, char**){
srand48(time(NULL));
vector<bool> winners;
vector<unsigned> results;
bool temp;
long double winner, stdev;
for(int i = 0; i < ITERATIONS; i++){
results.push_back(play(temp));
winners.push_back(temp);
}
cout << stats(results, winners, winner, stdev) << "\t";
cout << winner << "\t" << stdev << endl;
return 0;
}