Last active
August 30, 2019 02:53
-
-
Save Forty-Bot/5f098cdf0f47f02269df0cfde6eb038f 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
| /* Compile with ldc -O2 -ffast-math -mcpu=native cube.d */ | |
| 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 = 3; | |
| /* Use the first assignment when doing a rotisserie draft */ | |
| //immutable int PACK_COUNT = ROUNDS; | |
| immutable int PACK_COUNT = ROUNDS * PLAYERS; | |
| immutable int PACK_SIZE = 15; | |
| /* Total amount of extra cards to add for a forty-draft */ | |
| immutable int EXTRA_CARDS = 0; | |
| /* Where you sit */ | |
| immutable int SEAT_RANK = 0; | |
| static assert(SEAT_RANK < PLAYERS); | |
| static assert(PACK_COUNT * PACK_SIZE + EXTRA_CARDS <= CUBE_SIZE); | |
| immutable int REPS = 1_000_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 */ | |
| booster(); | |
| /* 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 = PACK_COUNT * 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 < PACK_COUNT * 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) { | |
| if (j == i % PLAYERS) { | |
| 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