/* Now, instead of iterating on every number from 1 to NB, we iterate on the numbers picked, calculating the winnings for every number between two adjacent numbers. For example, if the numbers picked are 3, 5, 10, ..., then we can calculate the winnings for 3&4 at one time, for 5 through 9 at one time, etc. */ #include #include #include #include #include #include using namespace std; void usage(string s) { cerr << "usage: keno-ll #balls #picked payout iterations-(zero-to-play) verbose(y|n)\n"; if (s != "") cerr << s << endl; exit(1); } class Keno_LL { public: int NB; int NP; int Wins, Losses, Ties; vector Numbs; set Picked; int Iterations; double Payout; double Winnings; double N; int Verbose; void Do_Picking(); void Calculate_Payout(int b); void Calculate_All(); }; void Keno_LL::Do_Picking() { int i, j, first, last, tmp; set ::iterator pbit; Picked.clear(); for (i = 0; i < NP; i++) { j = lrand48()%(NB-i); tmp = Numbs[j]; Numbs[j] = Numbs[NB-i-1]; Numbs[NB-i-1] = tmp; Picked.insert(Numbs[NB-i-1]); } if (Verbose) { cout << "Numbs Picked:"; for (pbit = Picked.begin(); pbit != Picked.end(); pbit++) { cout << " " << *pbit; } cout << ".\n"; } first = *(Picked.begin()); /* Sentinelize Picked */ last = *(Picked.rbegin()); Picked.insert(NB+first); Picked.insert(last-NB); } /* Now we calculate the values for all of the balls by looking at the intervals, rather than at individual balls. */ void Keno_LL::Calculate_All() { set ::iterator low, high; int x, highest; int nw, nl; highest = *Picked.rbegin(); low = Picked.begin(); high = low; high++; nw = 0; nl = 0; while (*high != highest) { x = *high - *low - 1; nw += (x/2); nl += (x - x/2); low++; high++; } Wins += nw; Losses += nl; Ties += NP; Winnings += nw*Payout; Winnings -= nl; N += NB; } void Keno_LL::Calculate_Payout(int b) { set ::iterator pbit; int u, l; double win; pbit = Picked.lower_bound(b); if (*pbit == b) { win = 0; Ties++; } else { u = *pbit; pbit--; l = *pbit; if (u - b < b - l) { win = Payout; Wins++; } else { win = -1; Losses++; } } Winnings += win; N++; if (Verbose) { if (win == 0) { printf(" Your ball was picked. +0: "); } else { printf(" D to higher: %d. D to lower: %d. %+.2lf: ", u-b, b-l, win); } printf("Total = %.2lf. Avg = %.6lf\n", Winnings, Winnings/N); } } int main(int argc, char **argv) { Keno_LL K; int i, b; string a5; if (argc != 6) usage(""); if (sscanf(argv[1], "%d", &(K.NB)) == 0 || K.NB <= 0) usage("#Numbs must be > 0\n"); if (sscanf(argv[2], "%d", &(K.NP)) == 0 || K.NP <= 0) usage("#Picked must be > 0\n"); if (sscanf(argv[3], "%lf", &(K.Payout)) == 0 || K.Payout <= 0) usage("Payout must be > 0\n"); if (sscanf(argv[4], "%d", &(K.Iterations)) == 0 || K.Iterations < 0) { usage("Iterations must be >= 0\n"); } a5 = argv[5]; if (a5 == "y" || a5 == "Y") { K.Verbose = 1; } else if (a5 == "n" || a5 == "N") { K.Verbose = 0; } else usage("Verbose must be y|n\n"); K.Winnings = 0; K.N = 0; K.Wins = 0; K.Losses = 0; K.Ties = 0; for (i = 1 ; i <= K.NB; i++) K.Numbs.push_back(i); srand48(time(0)); if (K.Iterations == 0) { while(1) { b = 0; do { if (K.Verbose) { cout << "Pick your ball: "; cout.flush(); } if (!(cin >> b)) { if (!K.Verbose && K.N > 0) { printf("Total = %.2lf. Avg = %.6lf. W/L/T: %d %d %d\n", K.Winnings, K.Winnings/K.N, K.Wins, K.Losses, K.Ties); } exit(0); } if (b <= 0 || b > K.NB) { cin.clear(); cout << "You must pick a ball between 1 and " << K.NB << ".\n"; } } while (b <= 0 || b > K.NB); K.Do_Picking(); K.Calculate_Payout(b); } } while (K.N < K.Iterations) { if (K.Verbose) printf("Picked %d\n", b); K.Do_Picking(); K.Calculate_All(); } if (!K.Verbose) { printf("Total = %.2lf. Avg = %.6lf. W/L/T: %d %d %d\n", K.Winnings, K.Winnings/K.N, K.Wins, K.Losses, K.Ties); } exit(0); }