Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <limits.h>
- #include <math.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define EVNT_RUNTIME_DAYS 21
- #define N_ITER 10000000
- #define N_MAX 36
- #define PTS_PER_DUPE 10
- #define PTS_PER_TDRAW 100
- #define ROLLS_PER_DAY 10
- double square(double x)
- {
- return x*x;
- }
- struct math_data
- {
- int gt_21;
- int max;
- int min;
- int mode;
- double median;
- double mean;
- double stdev;
- double variance;
- };
- struct math_data *math_data_new(int gt_21, int max, int min, int mode,
- double median, double mean, double stdev, double variance)
- {
- struct math_data *obj = malloc(sizeof(*obj));
- obj->gt_21 = gt_21;
- obj->max = max;
- obj->min = min;
- obj->mode = mode;
- obj->median = median;
- obj->mean = mean;
- obj->stdev = stdev;
- obj->variance = variance;
- return obj;
- }
- void math_data_print(struct math_data *data)
- {
- printf("-- Data Start --\n");
- printf(">21: %d (%.1lf%%)\n", data->gt_21,
- (double)data->gt_21 / N_ITER * 100);
- printf("max: %d\n", data->max);
- printf("min: %d\n", data->min);
- printf("mode: %d\n", data->mode);
- printf("median: %.1lf\n", data->median);
- printf("mean: %.15lf\n", data->mean);
- printf("stdev: %lf\n", data->stdev);
- printf("variance: %lf\n", data->variance);
- printf("-- Data End --\n");
- }
- struct bingo_data
- {
- int total_rolls;
- int days;
- int uniques;
- int dupes;
- };
- struct bingo_data *bingo_data_new(int total_rolls, int days,
- int uniques, int dupes)
- {
- struct bingo_data *obj = malloc(sizeof(*obj));
- obj->total_rolls = total_rolls;
- obj->days = days;
- obj->uniques = uniques;
- obj->dupes = dupes;
- return obj;
- }
- struct bingo_data *bingo()
- {
- bool set[N_MAX + 1] = {false};
- int total_rolls = 0, days = 0, uniques = 0, dupes = 0;
- for (bool done = false; !done; total_rolls++) {
- days = total_rolls % ROLLS_PER_DAY == 0 ? days + 1 : days;
- int r = random() % N_MAX + 1;
- if (set[r]) {
- dupes++;
- } else {
- set[r] = true;
- uniques++;
- }
- int numbers_left = (dupes * PTS_PER_DUPE) / PTS_PER_TDRAW;
- done = uniques + numbers_left >= N_MAX;
- }
- return bingo_data_new(total_rolls, days, uniques, dupes);
- }
- struct bingo_data *bingo_no_tdraw()
- {
- bool set[N_MAX + 1] = {false};
- int total_rolls = 0, days = 0, uniques = 0, dupes = 0;
- for (bool done = false; !done; total_rolls++) {
- days = total_rolls % ROLLS_PER_DAY == 0 ? days + 1 : days;
- int r = rand() % N_MAX + 1;
- if (set[r]) {
- dupes++;
- } else {
- set[r] = true;
- uniques++;
- }
- done = uniques >= N_MAX;
- }
- return bingo_data_new(total_rolls, days, uniques, dupes);
- }
- int get_gt_runtime(struct bingo_data **a)
- {
- int count = 0;
- for (size_t i = 0; i < N_ITER; i++)
- if (a[i]->days > EVNT_RUNTIME_DAYS)
- count++;
- return count;
- }
- int get_max(struct bingo_data **a)
- {
- int max = -1;
- for (size_t i = 0; i < N_ITER; i++)
- if (max < a[i]->days)
- max = a[i]->days;
- return max;
- }
- int get_min(struct bingo_data **a)
- {
- int min = INT_MAX;
- for (size_t i = 0; i < N_ITER; i++)
- if (min > a[i]->days)
- min = a[i]->days;
- return min;
- }
- double get_mode(struct bingo_data **a, int max)
- {
- int *freq_tbl = calloc(max + 1, sizeof(int));
- for (size_t i = 0; i < N_ITER; i++)
- freq_tbl[a[i]->days]++;
- int curr_max = -1;
- int mode = -1;
- for (size_t i = 1; i < max; i++) {
- if (freq_tbl[i] > curr_max) {
- curr_max = freq_tbl[i];
- mode = i;
- }
- }
- free(freq_tbl);
- return mode;
- }
- double get_median(struct bingo_data **a, int max)
- {
- int *csort = calloc(max + 1, sizeof(int));
- for (size_t i = 0; i < N_ITER; i++)
- csort[a[i]->days]++;
- int *rez = malloc(N_ITER * sizeof(int));
- for (size_t i = 1, k = 0; i < max + 1; i++)
- for (int j = 0; j < csort[i]; j++)
- rez[k++] = i;
- double ret;
- if (N_ITER % 2 == 0) {
- int lef_mid = (N_ITER / 2) - 1;
- int rgt_mid = N_ITER / 2;
- ret = ((double)rez[lef_mid] + (double)rez[rgt_mid]) / 2;
- } else {
- int mid = N_ITER / 2;
- ret = (double)rez[mid];
- }
- free(csort);
- free(rez);
- return ret;
- }
- double get_mean(struct bingo_data **a)
- {
- double mean = 0.0;
- for (size_t i = 0; i < N_ITER; i++)
- mean += (double)a[i]->days / N_ITER;
- return mean;
- }
- double get_stdev(struct bingo_data **a, double mean)
- {
- double stdev = 0.0;
- for (size_t i = 0; i < N_ITER; i++)
- stdev += square((double)a[i]->days - mean) / (double)N_ITER;
- return sqrt(stdev);
- }
- struct math_data *process(struct bingo_data **a)
- {
- printf("...Done. Processing data...\n");
- int gt_runtime = get_gt_runtime(a);
- int max = get_max(a);
- int min = get_min(a);
- int mode = get_mode(a, max);
- double median = get_median(a, max);
- double mean = get_mean(a);
- double stdev = get_stdev(a, mean);
- double variance = square(stdev);
- return math_data_new(gt_runtime, max, min, mode, median,
- mean, stdev, variance);
- }
- struct bingo_data **simulate(struct bingo_data*(*f)())
- {
- struct bingo_data **a = malloc(N_ITER * sizeof(struct bingo_data*));
- for (size_t i = 0; i < N_ITER; i++) {
- if (i % (N_ITER / 10) == 0)
- printf("%zu... Done.\n", i);
- a[i] = (*f)();
- }
- return a;
- }
- int main(void)
- {
- struct timespec ts;
- timespec_get(&ts, TIME_UTC);
- srandom(ts.tv_nsec ^ ts.tv_sec);
- printf("GFL Bingo: simulating for %d iterations...\n", N_ITER);
- struct bingo_data **a = simulate(bingo);
- struct math_data *a_data = process(a);
- math_data_print(a_data);
- for (size_t i = 0; i < N_ITER; i++)
- free(a[i]);
- free(a);
- free(a_data);
- printf("\n");
- printf("GFL Bingo (no targeted draws): simulating"
- " for %d iterations...\n", N_ITER);
- struct bingo_data **b = simulate(bingo_no_tdraw);
- struct math_data *b_data = process(b);
- math_data_print(b_data);
- for (size_t i = 0; i < N_ITER; i++)
- free(b[i]);
- free(b);
- free(b_data);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement