/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
/*
 * lottery.c
 * Copyright (C) 2018 TikalonLLC <gualtieri@ieee.org>
 * 
 * lottery is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * lottery is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
The RNG here is based on the code contained in the article, "64-bit KISS RNGs,"
by George Marsaglia (Feb 28, 2009).  As explained in the article, "This 64-bit 
KISS RNG has three components, each nearly good enough to serve alone. The 
components are:
Multiply-With-Carry (MWC), period (2^121+2^63-1)
Xorshift (XSH), period 2^64-1
Congruential (CNG), period 2^64

see https://www.thecodingforums.com/threads/64-bit-kiss-rngs.673657/
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define num1 43
#define num2 222
#define play_number 303

#define MWC (t=(x<<58)+c, c=(x>>6), x+=t, c+=(x<t), x)
#define XSH ( y^=(y<<13), y^=(y>>17), y^=(y<<43) )
#define CNG ( z=6906969069LL*z+1234567 )
#define KISS (MWC+XSH+CNG)
#define trials 100000000
#define iterations 1000

int i;
int j;
int n;
FILE *outdata;
clock_t t_start, t_end;
double pgm_time;
static unsigned long long
x=1234567890987654321ULL,c=123456123456123456ULL,
y=362436362436362436ULL,z=1066149217761810ULL,t;

void check_RNG(int lim)
{
//check random number generation by comparing frequency of occurence of
//two different numbers, num1 and num2
int count;
count = 0;

for(i=0;i<lim;i++)
{
//get three digit random number
t=KISS;
n= t%1000;
if (n==num1)
{
count--;
}
if (n==num2)
{
count++;
}
}
printf("%d\t%f\n",count,(float)count/lim);
}

int draw(int num)
{
//does lottery drawing against the number num
//returns times won

int count;
count = 0;

for(i=0;i<trials;i++)
{
//get three digit random number
t=KISS;
n= t%1000;
if (n==num)
{
count++;
}
}
return count;
}

int rand_draw()
{
//does lottery drawing against a random number
//returns times won

int count;
int rn;
count = 0;

for(i=0;i<trials;i++)
{
//get three digit random number
t=KISS;
n= t%1000;
//get random play number
t=KISS;
rn= t%1000;
if (n==rn)
{
count++;
}
}
return count;
}

int main(void)
{

t_start = clock();

//Open output datafile
if ((outdata = fopen("lottery_data.txt","w"))==NULL)
	{printf ("\nOutput file cannot be opened.\n");
	exit (1);}
else
{
printf("Output file = lottery_data.txt\n");
}

//KISS is a long long integer random number
//note that this RNG will give the same number sequence every time,
//which is OK for most simulations

//check_RNG(trials);

for (j=0;j<iterations;j++)
{
int wins;
wins=draw(play_number);
printf("%d\t",wins);
fprintf(outdata, "%d\t",wins);
wins=rand_draw();
printf("%d\n",wins);
fprintf(outdata, "%d\n",wins);
}

printf("\nDone.\n");

//Close output file
fclose(outdata);

t_end = clock();
pgm_time = ((double) (t_end - t_start))/CLOCKS_PER_SEC;

printf("\nProgram time = %f seconds\n",pgm_time);

return 0;
}
