Created
April 15, 2023 13:06
-
-
Save Lenart12/04aac8df92d411e0f4625845665ea0b0 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 <iostream> | |
#include <random> | |
#include <vector> | |
#include <array> | |
#include <pthread.h> | |
#include <iostream> | |
#include <algorithm> | |
#include <deque> | |
#include <fstream> | |
#include <iterator> | |
#include <sstream> | |
#include <stdio.h> | |
using std::deque; | |
using std::array; | |
using std::vector; | |
using std::cout; | |
using std::endl; | |
constexpr int joker_per_deck = 3; | |
constexpr int num_threads = 64; | |
constexpr int sim_per_thread = 10000; | |
enum class Card { | |
Joker, | |
As, | |
_2, _3, _4, _5, _6, _7, _8, _9, _10, | |
Bojan, Dama, Kralj | |
}; | |
void initialize_pile(deque<Card>& pile) { | |
for (int st_deckov = 0; st_deckov < 2; st_deckov++) { | |
for (int st_joker = 0; st_joker < joker_per_deck; st_joker++) | |
pile.push_back(Card::Joker); | |
for (int st_barve = 0; st_barve < 4; st_barve++) { | |
for (Card card = Card::As; card <= Card::Kralj; card = static_cast<Card>(uint8_t(card) + 1)) { | |
pile.push_back(card); | |
} | |
} | |
} | |
std::shuffle(pile.begin(), pile.end(), std::mt19937(std::random_device()())); | |
} | |
enum class Guess { | |
More, Same, Less, Joker | |
}; | |
enum class GuessStrategy { | |
AlwaysMore, | |
AlwaysLess, | |
AlwaysEqual, | |
AlwaysJoker, | |
MoreWhenGt7, | |
MoreWhenGt8, | |
Random, | |
}; | |
Guess guess_strategy(GuessStrategy sim_guess_strategy, Card top_card, std::mt19937& random) { | |
if (sim_guess_strategy == GuessStrategy::AlwaysMore) { | |
return Guess::More; | |
} else if (sim_guess_strategy == GuessStrategy::AlwaysLess) { | |
return Guess::Less; | |
} else if (sim_guess_strategy == GuessStrategy::AlwaysEqual) { | |
return Guess::Same; | |
} else if (sim_guess_strategy == GuessStrategy::AlwaysJoker) { | |
return Guess::Joker; | |
} else if (sim_guess_strategy == GuessStrategy::MoreWhenGt7) { | |
if (top_card == Card::As) return Guess::Less; | |
if (top_card > Card::_7) return Guess::Less; | |
return Guess::More; | |
} else if (sim_guess_strategy == GuessStrategy::MoreWhenGt8) { | |
if (top_card == Card::As) return Guess::Less; | |
if (top_card > Card::_8) return Guess::Less; | |
return Guess::More; | |
} else if (sim_guess_strategy == GuessStrategy::Random) { | |
return static_cast<Guess>(random() % 4); | |
} | |
return Guess::Joker; | |
} | |
constexpr bool correct_guess(Card new_card, Card top_card, Guess guess) { | |
// Karta na joker | |
if (top_card == Card::Joker) return true; | |
if (new_card == Card::Joker) { | |
// Joker in ugiba joker | |
if (guess == Guess::Joker) return true; | |
// Joker in ugiba drugo | |
else return false; | |
} | |
if (new_card == top_card) return guess == Guess::Same; | |
bool new_is_more = false; | |
// Preveri dvojka na as | |
if (top_card == Card::As) { | |
if (new_card == Card::_2) new_is_more = true; | |
else new_is_more = false; | |
// Preveri as na dvojko | |
} else if (top_card == Card::_2) { | |
if (new_card == Card::As) new_is_more = false; | |
else new_is_more = true; | |
// Ostalo | |
} else { | |
if (new_card == Card::As) new_is_more = true; | |
else new_is_more = new_card > top_card; | |
} | |
return (guess == Guess::More && new_is_more) || (guess == Guess::Less && !new_is_more); | |
} | |
uint16_t run_game_sim(int deck_size, GuessStrategy sim_guess_strategy) { | |
vector<Card> deck {}; | |
deck.resize(deck_size); | |
deque<Card> pile {}; | |
deque<Card> discard {}; | |
initialize_pile(pile); | |
for (auto& card: deck) { | |
card = pile.front(); | |
pile.pop_front(); | |
} | |
int shots_of_drink = 0; | |
int deck_progress = 0; | |
std::mt19937 random{std::random_device()()}; | |
while (shots_of_drink < 0xFFFF) { | |
auto top_card = deck[deck_progress]; | |
auto guess = guess_strategy(sim_guess_strategy, top_card, random); | |
if (pile.empty()) { | |
std::shuffle(discard.begin(), discard.end(), random); | |
pile.insert(pile.begin(), discard.begin(), discard.end()); | |
discard.clear(); | |
} | |
auto new_card = pile.front(); | |
pile.pop_front(); | |
discard.push_back(top_card); | |
deck[deck_progress] = new_card; | |
if (correct_guess(new_card, top_card, guess)) { | |
deck_progress++; | |
// Win | |
if (deck_progress == deck_size || guess == Guess::Joker) { | |
break; | |
} | |
} else { | |
// Dvojno pijes ce ugibas joker al pa ista al pa je joker al pa ista karta | |
if (guess == Guess::Joker || guess == Guess::Same || | |
new_card == Card::Joker || | |
correct_guess(new_card, top_card, Guess::Same) | |
) shots_of_drink++; | |
shots_of_drink++; | |
deck_progress = 0; | |
} | |
} | |
return std::min(shots_of_drink, 0xFFFF); | |
} | |
struct SimSettings | |
{ | |
int deck_size; | |
GuessStrategy guess_strategy; | |
}; | |
pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER; | |
deque<SimSettings> sim_queue {}; | |
extern "C" void* sim_thread(void* arg_) { | |
while(true) { | |
pthread_mutex_lock(&queue_mutex); | |
if (sim_queue.empty()) { | |
pthread_mutex_unlock(&queue_mutex); | |
break; | |
} | |
auto sim_settings = sim_queue.front(); | |
sim_queue.pop_front(); | |
printf("Processing task %d\n", sim_queue.size()); | |
pthread_mutex_unlock(&queue_mutex); | |
vector<uint16_t> games {}; | |
games.resize(sim_per_thread); | |
std::stringstream ss {}; | |
ss << "./avtobus-runs/strat-"; | |
switch (sim_settings.guess_strategy) { | |
case GuessStrategy::AlwaysMore: | |
ss << "more"; | |
break; | |
case GuessStrategy::AlwaysLess: | |
ss << "less"; | |
break; | |
case GuessStrategy::AlwaysEqual: | |
ss << "same"; | |
break; | |
case GuessStrategy::AlwaysJoker: | |
ss << "joker"; | |
break; | |
case GuessStrategy::MoreWhenGt7: | |
ss << "gt7"; | |
break; | |
case GuessStrategy::MoreWhenGt8: | |
ss << "gt8"; | |
break; | |
case GuessStrategy::Random: | |
ss << "rand"; | |
break; | |
} | |
ss << "-deck-" << sim_settings.deck_size; | |
ss << ".csv"; | |
std::ofstream output_file {ss.str()}; | |
output_file << "runs" << endl; | |
std::ostream_iterator<uint16_t> output_iterator {output_file, "\n"}; | |
for (auto& turns : games) { | |
turns = run_game_sim(sim_settings.deck_size, sim_settings.guess_strategy); | |
} | |
std::copy(std::begin(games), std::end(games), output_iterator); | |
} | |
return nullptr; | |
} | |
int main(int argc, char const *argv[]) | |
{ | |
array<pthread_t, num_threads> threads {}; | |
for (int i = 5; i < 55; i++) { | |
sim_queue.push_back({i, GuessStrategy::AlwaysMore}); | |
sim_queue.push_back({i, GuessStrategy::AlwaysLess}); | |
sim_queue.push_back({i, GuessStrategy::AlwaysEqual}); | |
sim_queue.push_back({i, GuessStrategy::AlwaysJoker}); | |
sim_queue.push_back({i, GuessStrategy::MoreWhenGt7}); | |
sim_queue.push_back({i, GuessStrategy::MoreWhenGt8}); | |
sim_queue.push_back({i, GuessStrategy::Random}); | |
} | |
int i = 0; | |
for (auto& thread: threads) { | |
pthread_create(&thread, nullptr, sim_thread, nullptr); | |
} | |
for (auto& thread: threads) { | |
pthread_join(thread, nullptr); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment