/* elecpred.c C program for helping to predict Canadian election results by Jeffrey Rosenthal (probability.ca), 2011 Compile with "cc -lm elecpred.c -o elecpred". Requires five auxiliary files: partynames, provincenames, results2008.csv, groundvals, and shiftvals. Note: results2008.csv is copied from: http://www.elections.ca/scripts/OVR2008/31/data/table_tableau12.csv After compiling, run the program with "elecpred a b c" where: a=0 for model (1), or a=11 for model (2) b=0 to not include the "ground" (over-performing) adjustments, or b=1 to include them c=0 to not include the "shift" adjustments, or c=1 to include them */ #include #include #include #include #define verboselevel 0 #define MAXLINELENGTH 160 #define MAXNUMFIELDS 20 #define MAXFIELDLENGTH 160 #define EFILENAME "results2008.csv" /* Global variables for storing vote results. */ #define MAXRIDINGNUM 99999 #define NUMREGIONS 5 #define NUMPARTIES 5 #define NUMPROVINCES 13 int ridingtot[MAXRIDINGNUM]; int ridingwinner[MAXRIDINGNUM]; int regiontot[NUMREGIONS]; int votecount[MAXRIDINGNUM][NUMPARTIES]; int regionvote[NUMREGIONS][NUMPARTIES]; double regionperc[NUMREGIONS][NUMPARTIES]; double totperc[NUMPARTIES]; int seattot[NUMPARTIES]; int votetot[NUMPARTIES]; int seatregion[NUMREGIONS][NUMPARTIES]; int ridingregion[MAXRIDINGNUM]; int tottot, numseats; int regionseats[NUMREGIONS]; double adjustedcount[MAXRIDINGNUM][NUMPARTIES]; int adjustedwinner[MAXRIDINGNUM]; int adjustedseatregion[NUMREGIONS][NUMPARTIES]; int adjustedseattot[NUMPARTIES]; double groundval[NUMPARTIES]; double shiftval[NUMPARTIES]; int USERATIO, USEGROUND, USESHIFT; /* Global variables for parsing input lines etc. */ char linedata[MAXNUMFIELDS][MAXFIELDLENGTH]; char theline[MAXLINELENGTH]; char prevline[MAXLINELENGTH]; char provincename[NUMPROVINCES][80]; char partyname[NUMPARTIES][80]; int totnumfields, filedone, maxnumcourses; int regionmap[] = {0,0,0,0,1,2,3,3,3,3,3,3,4}; char partytag[][20] = {"Con", "Lib", "NDP", "Bloc", "Green"}; char regiontag[][20] = {"Atlantic", "Quebec", "Ontario", "Praries", "B.C."}; /* BEGIN MAIN PROGRAM. */ int main(int argc, char **argv) { /* Initial declarations. */ FILE *fp; char tmpstring[MAXLINELENGTH]; int i, j, tmptot; int riding, party, votes, province, region, winner, ridingmax; double pollreg[NUMREGIONS][NUMPARTIES]; double polltot[NUMPARTIES]; /* Read in the province names. */ if ((fp = fopen("provincenames","r")) == NULL) { printf("OOPS, unable to read file %s.\n", "provincenames"); exit(1); } for (i=0; i= 2) USERATIO = atoi(argv[1]); if (argc >= 3) USEGROUND = atoi(argv[2]); if (argc >= 4) USESHIFT = atoi(argv[3]); if (USEGROUND==0) for (i=0; i0) printf("\n\n"); fflush(stdout); nextline(fp); /* Omit headers. */ filedone = 0; while (filedone==0) { /* Read a line of the file. */ nextline(fp); /* Process the line. */ if (filedone==0) { parseline(); /* printf("**%s**\n", linedata[0]); */ riding = atoi(linedata[2]); votes = atoi(linedata[6]); /* Identify province. */ province = -1; for (i=0; i=2) printf("province=%d, region=%d\n", province, region); /* Identify party. */ party = -1; for (i=0; i<5; i++) { if (!strcmp(linedata[3]+strlen(linedata[3])-strlen(partyname[i]), partyname[i])) party = i; } if (verboselevel>=2) printf("riding=%d, votes=%d, province=%d, party=%d\n", riding, votes, province, party); ridingtot[riding] = ridingtot[riding] + votes; regiontot[region] = regiontot[region] + votes; if (party >= 0) { votecount[riding][party] = votes; regionvote[region][party] = regionvote[region][party] + votes; votetot[party] = votetot[party] + votes; } } /* End of "if (filedone==0)" branch. */ } /* End of "while" loop. */ printf("done.\n"); fclose(fp); /* Compute total number of votes cast. */ tottot = 0; for (i=0; i= 1) printf("tottot=%d\n", tottot); /* Compute regional percentages. */ for (i=0; i= 1) printf("regionperc[%d][%d] = 100 * %d / %d = %f\n", i, j, regionvote[i][j], regiontot[i], regionperc[i][j]); } } for (j=0; j2) { for (j=0; j0) { numseats++; regionseats[ridingregion[i]] = regionseats[ridingregion[i]] + 1; winner = ridingmax = -1; for (j=0; j ridingmax) { winner = j; ridingmax = votecount[i][j]; } } if (verboselevel >= 2) printf("winner of riding %d is %d\n", i, winner); if (winner<0) { printf("OOPS, unable to identify winner in riding %d.\n", i); exit(1); } ridingwinner[i] = winner; seatregion[ridingregion[i]][winner] = seatregion[ridingregion[i]][winner] + 1; seattot[winner] = seattot[winner] + 1; } } /* Output national election results. */ printf("\n=============================== ELECTION RESULTS ============\n"); printf("\nCANADA:\n\t"); for (j=0; j= 1) printf("pollreg[%d][%d]=%f\n", j, i, pollreg[j][i]); } } fclose(fp); /* Output the election results summary. */ printf("\n\n=============================== ELECTION RESULTS ======================\n"); printf("\n\t"); for (j=0; j0) { region = ridingregion[i]; for (j=0; j ridingmax) { winner = j; ridingmax = adjustedcount[i][j]; } } if (verboselevel >= 2) printf("adjusted winner of riding %d is %d\n", i, winner); if (winner<0) { printf("OOPS, unable to identify adjusted winner in riding %d.\n", i); exit(1); } adjustedwinner[i] = winner; adjustedseatregion[region][winner] = adjustedseatregion[region][winner] + 1; adjustedseattot[winner] = adjustedseattot[winner] + 1; } } /* Output predicted seat counts summary. */ printf("\n\n=============================== PREDICTED SEAT COUNTS ================\n"); printf("\n\t"); for (j=0; j= MAXNUMFIELDS) { printf("ERROR: maximum number of fields exceeded.\n"); exit(1); } } else if ( (theline[linespot]=='\n') || (theline[linespot]=='\0') ) { /* Deal with end of line. */ done = 1; } else { /* Deal with ordinary characters. */ linedata[fieldnum][fieldlength] = theline[linespot]; fieldlength++; if (fieldlength >= MAXFIELDLENGTH) { linedata[fieldnum][fieldlength] = '\0'; printf("ERROR: field length %d >= %d: %s\n", fieldlength, MAXFIELDLENGTH, linedata[fieldnum]); exit(1); } } linespot++; } totnumfields = fieldnum; if (verboselevel>2) printf("parseline: totnumfields=%d\n", totnumfields); return(0); } int divides(int aa, int bb) { return( (bb/aa)*aa == bb ); }