5
\$\begingroup\$

I want to play around with the Powerball lotto drawing history. What other probability theories could I try or what other probability class libraries exist. The code parses the file very quickly but is there a better way to go about it?

I am working on a multiple regression analysis with the first white_ball as a dependent variable.

#include <iostream>
#include <algorithm>
#include <sstream>
#include <fstream>
#include "linear.h" // http://www.codecogs.com/code/maths/approximation/regression/linear.php
#include <string>

using namespace std;

// Powerball rules.
// (http://en.wikipedia.org/wiki/Powerball)
const int POWERBALL_WHITE = 59;     // White balls number 1-59
const int WHITE_DRAWS = 5;          // Only 5 balls are drawn.
const int POWERBALL_RED = 35;       // Red balls number 1-35
const int REB_DRAWS = 1;            // Only 1 ball is drawn.

// Parse rules.
const int MAX_LINE = 37;
const char* DELIMITER_DATE = "/";   // Draw date format is separated by forward slash.

typedef struct {
    int month;
    int day;
    int year;
    int white_ball_1;
    int white_ball_2;
    int white_ball_3;
    int white_ball_4;
    int white_ball_5;
    int reb_ball;
} Powerball;

int main (int argc, char** argv) {
    // Open the historical data file.
    // (http://www.powerball.com/powerball/pb_nbr_history.asp)
    ifstream lotto;
    lotto.open("lotto.txt");
    if (!lotto.good())
        return 1;

    // How many weekly drawing have taken place?
    int number_Drawings = (int)count(istreambuf_iterator<char>(lotto), istreambuf_iterator<char>(), '\n') - 1;
    lotto.seekg(0);
    // Create Powerball drawing array.
    Powerball *drawings;
    drawings = (Powerball*) malloc(number_Drawings * sizeof(Powerball));

    // Parse loto results to Powerball array.
    lotto.ignore(50, '\n'); // Skip first line with category references.
    while (!lotto.eof()) {
        Powerball draw;

        // Line objects to parse.
        static int n;
        int month, day, year;
        char DELIMITER; // Date delimiter like variable.
        int white_1,white_2, white_3, white_4, white_5, red;

        lotto >> month >> DELIMITER >> day >> DELIMITER >> year >> white_1 >> white_2 >> white_3 >> white_4 >> white_5 >> red;

        draw.month = month;
        draw.day = day;
        draw.year = year;
        draw.white_ball_1 = white_1;
        draw.white_ball_2 = white_2;
        draw.white_ball_3 = white_3;
        draw.white_ball_4 = white_4;
        draw.white_ball_5 = white_5;
        draw.reb_ball = red;

        drawings[n++] = draw;
        if (lotto.peek() != '\n') // For entries with Plus Ball or extra characters
            lotto.ignore(10, '\n');    
    }
    lotto.close();

    // Create linear regression arrays variables.
    double lin_reg_1[number_Drawings];
    double lin_reg_2[number_Drawings];
    double lin_reg_3[number_Drawings];
    double lin_reg_4[number_Drawings];
    double lin_reg_5[number_Drawings];
    for (int i = 0; i < number_Drawings; i++) {
        lin_reg_1[i] = drawings[i].white_ball_1;
        lin_reg_2[i] = drawings[i].white_ball_2;
        lin_reg_3[i] = drawings[i].white_ball_3;
        lin_reg_4[i] = drawings[i].white_ball_4;
        lin_reg_5[i] = drawings[i].white_ball_5;
    }

    cout << "There are " << number_Drawings << " drawings that have taken place since " <<
            drawings[number_Drawings].month << "/" << drawings[number_Drawings].day << "/" << drawings[number_Drawings].year
            << endl << endl;

    cout << "------------------------------------------------------------------------" << endl;
    cout << "Linear regression test 1. White_1 dependent, White_2 independent" << endl;
    cout << "------------------------------------------------------------------------" << endl;
    Maths::Regression::Linear reg_a(number_Drawings,lin_reg_1,lin_reg_2);
    cout << "Slope = "                  << reg_a.getSlope()         << endl;
    cout << "Intercept = "              << reg_a.getIntercept()     << endl;
    cout << "Regression coefficient = " << reg_a.getCoefficient()   << endl << endl;

    cout << "------------------------------------------------------------------------" << endl;
    cout << "Linear regression test 2. White_2 dependent, White_3 independent" << endl;
    cout << "------------------------------------------------------------------------" << endl;
    Maths::Regression::Linear reg_b(number_Drawings,lin_reg_2,lin_reg_3);
    cout << "Slope = "                  << reg_b.getSlope()         << endl;
    cout << "Intercept = "              << reg_b.getIntercept()     << endl;
    cout << "Regression coefficient = " << reg_b.getCoefficient()   << endl << endl;

    cout << "------------------------------------------------------------------------" << endl;
    cout << "Linear regression test 3. White_3 dependent, White_4 independent" << endl;
    cout << "------------------------------------------------------------------------" << endl;
    Maths::Regression::Linear reg_c(number_Drawings,lin_reg_3,lin_reg_4);
    cout << "Slope = "                  << reg_c.getSlope()         << endl;
    cout << "Intercept = "              << reg_c.getIntercept()     << endl;
    cout << "Regression coefficient = " << reg_c.getCoefficient()   << endl << endl;

    cout << "------------------------------------------------------------------------" << endl;
    cout << "Linear regression test 4. White_4 dependent, White_5 independent" << endl;
    cout << "------------------------------------------------------------------------" << endl;
    Maths::Regression::Linear reg_d(number_Drawings,lin_reg_4,lin_reg_5);
    cout << "Slope = "                  << reg_d.getSlope()         << endl;
    cout << "Intercept = "              << reg_d.getIntercept()     << endl;
    cout << "Regression coefficient = " << reg_d.getCoefficient()   << endl << endl;

    cout << "------------------------------------------------------------------------" << endl;
    cout << "Linear regression test 5. White_5 dependent, White_1 independent" << endl;
    cout << "------------------------------------------------------------------------" << endl;
    Maths::Regression::Linear reg_e(number_Drawings,lin_reg_5,lin_reg_1);
    cout << "Slope = "                  << reg_e.getSlope()         << endl;
    cout << "Intercept = "              << reg_e.getIntercept()     << endl;
    cout << "Regression coefficient = " << reg_e.getCoefficient()   << endl << endl;

    return 0;
}
\$\endgroup\$
6
\$\begingroup\$

My suggestions won't make your code faster, I focused on idiomatic and clear code. It's already quite nice as it is. :)

// Powerball rules.
// (http://en.wikipedia.org/wiki/Powerball)
const int POWERBALL_WHITE = 59;     // White balls number 1-59
const int WHITE_DRAWS = 5;          // Only 5 balls are drawn.
const int POWERBALL_RED = 35;       // Red balls number 1-35
const int REB_DRAWS = 1;            // Only 1 ball is drawn.

Did you mean RED_DRAWS? You're not using any of those constants. Interestingly, it does make the code clearer for someone who doesn't know the rules.

// Parse rules.
const int MAX_LINE = 37;
const char* DELIMITER_DATE = "/";   // Draw date format is separated by forward slash.

typedef struct {
    int month;
    int day;
    int year;
    int white_ball_1;
    int white_ball_2;
    int white_ball_3;
    int white_ball_4;
    int white_ball_5;

A static array would be easier here: int whiteballes[WHITE_DRAWS].

    int reb_ball;

Did you mean red_ball?

} Powerball;

This is a C-style struct, but a C++-style struct would have been more idiomatic.

int main (int argc, char** argv) {
    // Open the historical data file.
    // (http://www.powerball.com/powerball/pb_nbr_history.asp)
    ifstream lotto;
    lotto.open("lotto.txt");

Isn't it simpler to use the constructor of std::ifstream?

    if (!lotto.good())
        return 1;

This can be very surprising if nothing is printed on std::cerr.

    // How many weekly drawing have taken place?
    int number_Drawings = (int)count(istreambuf_iterator<char>(lotto), istreambuf_iterator<char>(), '\n') - 1;
    lotto.seekg(0);
    // Create Powerball drawing array.
    Powerball *drawings;
    drawings = (Powerball*) malloc(number_Drawings * sizeof(Powerball));

C-style allocation, when you could have used a C++03 vector or a C++11 fixed-size array. You're not even freeing this memory.

    // Parse loto results to Powerball array.
    lotto.ignore(50, '\n'); // Skip first line with category references.

Avoid magic numbers, this a good fit for a constant.

    while (!lotto.eof()) {
        Powerball draw;

        // Line objects to parse.
        static int n;
        int month, day, year;
        char DELIMITER; // Date delimiter like variable.
        int white_1,white_2, white_3, white_4, white_5, red;

        lotto >> month >> DELIMITER >> day >> DELIMITER >> year >> white_1 >> white_2 >> white_3 >> white_4 >> white_5 >> red;

Why don't you read directly in draw? This would make the following lines unnecessary.

        draw.month = month;
        draw.day = day;
        draw.year = year;
        draw.white_ball_1 = white_1;
        draw.white_ball_2 = white_2;
        draw.white_ball_3 = white_3;
        draw.white_ball_4 = white_4;
        draw.white_ball_5 = white_5;
        draw.reb_ball = red;

        drawings[n++] = draw;
        if (lotto.peek() != '\n') // For entries with Plus Ball or extra characters
            lotto.ignore(10, '\n');    

General formatting advice: avoid long lines and spaces after instructions.

    }
    lotto.close();

    // Create linear regression arrays variables.
    double lin_reg_1[number_Drawings];
    double lin_reg_2[number_Drawings];
    double lin_reg_3[number_Drawings];
    double lin_reg_4[number_Drawings];
    double lin_reg_5[number_Drawings];

What about a matrix?

    for (int i = 0; i < number_Drawings; i++) {
        lin_reg_1[i] = drawings[i].white_ball_1;
        lin_reg_2[i] = drawings[i].white_ball_2;
        lin_reg_3[i] = drawings[i].white_ball_3;
        lin_reg_4[i] = drawings[i].white_ball_4;
        lin_reg_5[i] = drawings[i].white_ball_5;
    }

If white_ball was an array, you could have only one affectation in your loop.

\$\endgroup\$
  • 1
    \$\begingroup\$ @BrandonClark (A1) I do mean a C++ struct, eg. struct Powerball { ... }, since everything is visible. (A9) somethings like a = 2; . (A10) To be clear, matrix here means vector of vector or array of array. \$\endgroup\$ – Quentin Pradet May 14 '13 at 14:04
  • 2
    \$\begingroup\$ Don't loop on .eof(), it doesn't do what you want. Loop on the stream state itself. \$\endgroup\$ – Yuushi May 14 '13 at 15:32
  • 1
    \$\begingroup\$ @BrandonClark stackoverflow.com/questions/14615671/… \$\endgroup\$ – Yuushi May 15 '13 at 5:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.