Skip to content

Instantly share code, notes, and snippets.

@weirddan455
Last active April 24, 2022 04:44
Show Gist options
  • Save weirddan455/f8ab4cb2b82934d78071efb6742a499a to your computer and use it in GitHub Desktop.
Save weirddan455/f8ab4cb2b82934d78071efb6742a499a to your computer and use it in GitHub Desktop.
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
struct rng {
uint64_t state;
uint64_t inc;
};
struct rng rngState;
bool seed_rng(void)
{
int fd = open("/dev/urandom", O_RDONLY);
if (fd == -1) {
printf("Failed to open /dev/urandom: %s\n", strerror(errno));
return false;
}
uint64_t buf[2];
ssize_t bytes = read(fd, buf, 16);
if (bytes != 16) {
if (bytes == -1) {
printf("Failed to read from /dev/urandom: %s\n", strerror(errno));
} else {
printf("16 bytes expected. Read %zd\n", bytes);
}
close(fd);
return false;
}
rngState.state = buf[0];
rngState.inc = buf[1] | 1;
close(fd);
return true;
}
static uint32_t pcg_random(void)
{
uint64_t oldstate = rngState.state;
rngState.state = oldstate * 6364136223846793005ULL + rngState.inc;
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((0 - rot) & 31));
}
static uint32_t pcg_ranged_random(uint32_t range)
{
uint32_t x = pcg_random();
uint64_t m = (uint64_t)x * (uint64_t)range;
uint32_t l = (uint32_t)m;
if (l < range) {
uint32_t t = (0 - range) % range;
while (l < t) {
x = pcg_random();
m = (uint64_t)x * (uint64_t)range;
l = (uint32_t)m;
}
}
return m >> 32;
}
void shuffle_deck(bool *deck)
{
for (uint32_t i = 59; i > 0; i--) {
uint32_t random = pcg_ranged_random(i + 1);
bool temp = deck[i];
deck[i] = deck[random];
deck[random] = temp;
}
}
int main(void)
{
if (!seed_rng()) {
puts("Failed to seed RNG");
return 1;
}
bool deck[60]; // true = land, false = non-land
for (int i = 0; i < 24; i++) {
deck[i] = true;
}
for (int i = 24; i < 60; i++) {
deck[i] = false;
}
int floods = 0;
int games = 100000;
for (int i = 0; i < games; i++) {
shuffle_deck(deck);
int lands = 0;
for (int i = 0; i < 60; i++) {
if (deck[i]) {
lands++;
if (lands >= 5) {
floods++;
break;
}
} else {
lands = 0;
}
}
}
double percent = ((double)floods / (double)games) * 100.0;
printf("Out of %d games, 5 lands in a row happened in %d\n%f%% chance\n", games, floods, percent);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment