Last active
April 24, 2022 04:44
-
-
Save weirddan455/f8ab4cb2b82934d78071efb6742a499a to your computer and use it in GitHub Desktop.
This file contains hidden or 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 <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