Formula 1 Season Standings
Autumn Tournament (2009)
Submission name: formula1.cpp
Problem summary
This is an output-only task. Given the supplied 2009 Formula 1 results file, prepare final driver standings. Places 1..8 earn 10,8,6,5,4,3,2,1 points, except Malaysia awards half points. Break equal totals by more wins, then more second places, and so on. Submit the generated output file, not this generator program.
Source clarification. Output-only format: the original judge requires formula1.out, not a program. The fixed input data is available inside https://infos.infosbg.com/files/Contests/ETI/2009/C/problems/formula1.zip . The generator below uses standard input/output for convenient local redirection.
Input
Official data file: 17 blocks, each with a race heading such as Malaysia, 05/04/2009 followed by eight lines such as 1. Jenson Button, Brawn-Mercedes. For the program below redirect that file to standard input.
Output
One line per scoring driver: rank. name: points. Use exactly one space after the period and colon, no empty lines, and print .5 when necessary.
Constraints
The fixed original season contains 17 races and eight scoring places per race. The supplied archive contains the race results and expected standings.
Worked example
Independently prepared two-race teaching example; not the fixed contest answer file.
Input
Australia, 29/03/2009 1. Driver A, Team 2. Driver B, Team 3. Driver C, Team 4. Driver D, Team 5. Driver E, Team 6. Driver F, Team 7. Driver G, Team 8. Driver H, Team Malaysia, 05/04/2009 1. Driver A, Team 2. Driver B, Team 3. Driver C, Team 4. Driver D, Team 5. Driver E, Team 6. Driver F, Team 7. Driver G, Team 8. Driver H, Team
Output
1. Driver A: 15 2. Driver B: 12 3. Driver C: 9 4. Driver D: 7.5 5. Driver E: 6 6. Driver F: 4.5 7. Driver G: 3 8. Driver H: 1.5
Solution analysis
- This task is about preparing an answer file rather than submitting source code. Download the official archive linked in the source clarification, take its Formula-1-Results-2009.in data, and run the generator with input redirection. Save standard output as formula1.out for the output-only judge.
- Store doubled points as integers, avoiding floating-point formatting. A normal win adds 20 doubled points; a Malaysia win adds 10. For each driver also count finishes at each of the eight positions. Extract the driver name between the first period and the comma; the team name does not affect standings.
- Sort by doubled points descending, then by the entire finish-count array descending. This exactly implements more wins, then more second places, and so on. The fixed official data has no unresolved tie after those criteria; name order is used only as a deterministic fallback for other inputs.
- The educational example uses two artificial races with the same top eight drivers. Driver D earns 5+2.5=7.5 points, so doubled storage is 15 and output is 7.5. On the full original season file the first line is 1. Jenson Button: 95, as required by the source.
Why it works
Each race line contributes its position’s prescribed points exactly once. Doubling preserves exact integer and half-point values. A lexicographic descending comparison of finish frequencies implements the stated successive tie breakers. Thus sorting these accumulated records yields the requested standings.
Watch out. This program is a generator, not a valid source-code submission to the original output-only task. Do not count team names as drivers or forget Malaysia’s half points. Do not print .0 for integral totals.
Commented C++17 solution
Complete C++17 answer-file generator. Do not submit this source to the original output-only judge.
#include<algorithm>
#include<array>
#include<iostream>
#include<map>
#include<string>
#include<vector>
using namespace std;
struct Driver{
string name;
int doubledPoints=0;
array<int,8>finishes{};
};
int main(){
array<int,8>points{10,8,6,5,4,3,2,1};
map<string,Driver>drivers;
string heading;
while(getline(cin,heading)){
if(heading.empty()){
continue;
}
bool halfPoints=heading.find("Malaysia")!=string::npos;
for(int place=0;place<8;place++){
string line;
getline(cin,line);
size_t period=line.find('.');
size_t comma=line.find(',',period);
string name=line.substr(period+2,comma-period-2);
Driver&driver=drivers[name];
driver.name=name;
// Doubled points represent halves exactly with integers.
driver.doubledPoints+=points[place]*(halfPoints?1:2);
driver.finishes[place]++;
}
}
vector<Driver>ranking;
for(const auto&entry:drivers){
ranking.push_back(entry.second);
}
sort(ranking.begin(),ranking.end(),[](const Driver&a,const Driver&b){
if(a.doubledPoints!=b.doubledPoints){
return a.doubledPoints>b.doubledPoints;
}
if(a.finishes!=b.finishes){
return a.finishes>b.finishes;
}
return a.name<b.name;
});
for(size_t i=0;i<ranking.size();i++){
cout<<i+1<<". "<<ranking[i].name<<": "<<ranking[i].doubledPoints/2;
if(ranking[i].doubledPoints%2!=0){
cout<<".5";
}
cout<<'\n';
}
}