Skip to content

Instantly share code, notes, and snippets.

@Forty-Bot
Created August 29, 2019 21:01
Show Gist options
  • Select an option

  • Save Forty-Bot/58e65868bc09e77913f84433e019fbee to your computer and use it in GitHub Desktop.

Select an option

Save Forty-Bot/58e65868bc09e77913f84433e019fbee to your computer and use it in GitHub Desktop.
import core.stdc.stdio : stderr;
import std.bitmanip;
import std.algorithm.comparison;
import std.algorithm.iteration;
import std.math;
import std.range;
import std.random;
import std.stdio;
immutable int CUBE_SIZE = 360;
immutable int BITS_SIZE = ((CUBE_SIZE - 1) / size_t.sizeof / 8) + 1;
immutable int PLAYERS = 8;
immutable int ROUNDS = 24;
immutable int PACK_COUNT = ROUNDS;
//immutable int PACK_COUNT = ROUNDS * PLAYERS;
immutable int PACK_SIZE = 15;
immutable int EXTRA_CARDS = 0;
immutable int SEAT_RANK = 0;
static assert(SEAT_RANK < PLAYERS);
static assert(PACK_COUNT * PACK_SIZE + EXTRA_CARDS <= CUBE_SIZE);
immutable int REPS = 1_00_000;
immutable int STATS = CUBE_SIZE;
size_t[PACK_COUNT * BITS_SIZE] packs_buf;
BitArray[PACK_COUNT] packs;
size_t[BITS_SIZE] pool_buf;
BitArray pool;
immutable int[CUBE_SIZE] sort_cube = iota(360).array();
int[CUBE_SIZE] shuf_cube;
int[STATS] counts;
void main()
{
packs = packs_buf[].chunks(BITS_SIZE).map!(p => BitArray(p, CUBE_SIZE)).array;
pool = BitArray(pool_buf, CUBE_SIZE);
do_sim();
foreach (i; 0 .. STATS)
writefln("%d,%1.6f", i + 1, cast(real)counts[i] / (i + 1) / REPS);
}
void do_sim() {
foreach (r; 0 .. REPS) {
packs_buf[] = 0;
pool_buf[] = 0;
/*
* Even though the packs are bitmaps, the easiest way to shuffle is to shuffle the whole thing as an
* array and then slice it up for the packs
*/
shuf_cube = sort_cube;
shuf_cube[].randomShuffle(rndGen);
foreach (pack, shuf_pack; zip(packs[], shuf_cube[].chunks(PACK_SIZE)))
foreach (card; shuf_pack)
pack[card] = 1;
/* Do the draft */
rotisserie();
/* Calculate some stats */
auto count = 0;
foreach (i; 0 .. STATS) {
count += pool[i];
counts[i] += count;
}
if ((r & 0xFFF) == 0)
fprintf(stderr, "%d\n", (r));
}
}
void booster() {
foreach (round, round_packs; packs[].chunks(PLAYERS).enumerate()) {
if (round == ROUNDS)
break;
/* we change seats while the packs stay still */
foreach (i; 0 .. PACK_SIZE) {
auto j = i % PLAYERS;
foreach (k; 0 .. PLAYERS) {
auto pack = round_packs[k];
if (j == k) {
auto card = pack.bitsSet.front;
pool[card] = 1;
pack[card] = 0;
} else {
pack[pack.bitsSet.drop(uniform(0, PACK_SIZE - i, rndGen)).front] = 0;
}
}
}
}
}
void forty() {
size_t l = PLAYERS * PACK_SIZE;
foreach (round, round_packs; packs[].chunks(PLAYERS).enumerate()) {
if (round == ROUNDS)
break;
/* we change seats while the packs stay still */
foreach (i; 0 .. PACK_SIZE) {
auto j = i % PLAYERS;
foreach (k; 0 .. PLAYERS) {
auto pack = round_packs[k];
if (j == k) {
auto card = pack.bitsSet.front;
pool[card] = 1;
pack[card] = 0;
} else {
pack[pack.bitsSet.drop(uniform(0, PACK_SIZE - i, rndGen)).front] = 0;
}
}
/* Add some more cards */
if (l < PLAYERS * PACK_SIZE + EXTRA_CARDS)
foreach (pack; round_packs)
pack[shuf_cube[l++]] = 1;
}
}
}
/* Also rochester */
void rotisserie() {
foreach (round; 0 .. ROUNDS) {
auto pack = packs[round];
auto j = (SEAT_RANK + round) % PLAYERS;
foreach (i; 0 .. PACK_SIZE - DROPPED) {
foreach (k; 0 .. min(PLAYERS, PACK_SIZE - (i * PLAYERS))) {
if (j == k) {
auto card = pack.bitsSet.front;
pool[card] = 1;
pack[card] = 0;
} else {
pack[pack.bitsSet.drop(uniform(0, PACK_SIZE - i, rndGen)).front] = 0;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment