Skip to content

Instantly share code, notes, and snippets.

@Lenart12
Created April 15, 2023 13:06
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 Lenart12/04aac8df92d411e0f4625845665ea0b0 to your computer and use it in GitHub Desktop.
Save Lenart12/04aac8df92d411e0f4625845665ea0b0 to your computer and use it in GitHub Desktop.
#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