My task: find all trains, which overtake another train and return their trainId.
Implementation-suggestion:
for all trains B
for all trains A
find station C, where A departs and B later departs than A (the earliest one)
if there is such one
for all stations D, where A stops after C and B also stops
if B stops at D earlier than A, then B is a overtaker!
I implemented the algorithm, but it is very very slow, I need some help to improve this code. I have 3 input (.dat) files, where I build of each a Object which is like a list (StationList, TrainList, Schedule) and of each line (in this files) a own Object (Train, Station, Entry) which are all entries of the respective "list".
train.h
#ifndef TRAIN_H
#define TRAIN_H
#include <string>
#include <vector>
using namespace std;
class Train{
public:
Train(string s);
Train(int pId); //for comparisons
bool operator< (const Train &t) const;
int getId() { return id; }
private:
int id;
int numberOfWaggons;
};
class TrainList{
public:
TrainList(char const *filename);
Train give(int index) { return trains[index]; }
int length() { return trains.size(); }
private:
vector<Train> trains;
};
#endif
train.cc
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include "train.h"
using namespace std;
Train::Train(string s) {
stringstream ss(s);
ss >> id >> numberOfWaggons;
}
Train::Train(int pId) {
id = pId;
}
TrainList::TrainList(char const *filename){
ifstream input(filename);
string line;
while(getline(input,line))
trains.push_back(Train(line));
sort(trains.begin(), trains.end());
}
bool Train::operator< (const Train &t) const {
return id < t.id;
}
station.h
#ifndef STATION_H
#define STATION_H
#include <string>
#include <vector>
using namespace std;
class Station {
public:
Station(string s);
Station(int pId); // for comparisons
string getName();
bool operator< (const Station &s) const;
int getId(){ return id; }
private:
int id;
string name;
};
class StationList {
public:
StationList(char const *filename);
Station give(int index) { return stations[index]; }
int length() { return stations.size(); }
private:
vector<Station> stations;
};
#endif
station.cc
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include "station.h"
using namespace std;
Station::Station(string s) {
stringstream ss(s);
ss >> id >> name;
}
Station::Station(int pId) {
id = pId;
}
StationList::StationList(char const *filename){
ifstream input(filename);
string line;
while(getline(input,line))
stations.push_back(Station(line));
sort(stations.begin(), stations.end());
}
string Station::getName() {
return name;
}
bool Station::operator< (const Station &s) const {
return id < s.id;
}
schedule.h
#ifndef SCHEDULE_H
#define SCHEDULE_H
#include <string>
#include <vector>
using namespace std;
class Entry{
public:
Entry(string s);
Entry(int pId, int time, int param); //time=dep or arr, param 0 for time=arrival //for comparisons
bool operator< (const Entry &e) const;
bool operator== (const Entry &e) const;
int getTrainId(){ return trainId; }
int getArrival(){ return arrival; }
int getDeparture(){ return departure; }
private:
int trainId, stationId, arrival, departure, parameter;
};
class Schedule{
public:
Schedule(char const *filename);
int lookup(int trainId, int stationId, int param);
int length() { return allEntries.size(); }
Entry give(int index) { return allEntries[index]; }
private:
vector<Entry> allEntries;
};
#endif
schedule.cc
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include "schedule.h"
using namespace std;
Entry::Entry(string s) {
stringstream ss(s);
int arrHour, arrMin, depHour, depMin;
ss >> trainId >> stationId >> arrHour >> arrMin >> depHour >> depMin;
/* Then it is not the first, but the last train */
if(depHour == 0 && depMin == 0)
depHour = 24;
arrival = arrHour*60+arrMin;
departure = depHour*60+depMin;
}
Entry::Entry(int pId, int statId, int param) {
trainId = pId;
stationId = statId;
parameter = param;
}
Schedule::Schedule(char const *filename){
ifstream input(filename);
string line;
while(getline(input,line)){
allEntries.push_back(Entry(line));
}
sort(allEntries.begin(), allEntries.end());
}
int Schedule::lookup(int trainId, int stationId, int param) {
Entry item(trainId, stationId, param);
vector<Entry>::iterator it = find(allEntries.begin(), allEntries.end(), item);
if (it != allEntries.end()){
Entry e = *it;
return (param == 0) ? e.getArrival() : e.getDeparture();
}
else
return -1;
}
bool Entry::operator< (const Entry &e) const {
return (trainId == e.trainId && arrival < e.arrival) || trainId < e.trainId;
}
bool Entry::operator== (const Entry &e) const {
return (trainId == e.trainId && stationId == e.stationId);
}
and finally (here is the very ugly algorithm):
main.cc
#include <iostream>
#include <fstream>
#include "station.h"
#include "train.h"
#include "schedule.h"
using namespace std;
int main(int argc, char *argv[]) {
StationList stations = StationList("stations.dat");
TrainList trains = TrainList("trains.dat");
Schedule schedule = Schedule("schedule.dat");
for(int b = 0; b < trains.length(); b++){
for(int a = 0; a < trains.length(); a++){
for(int c = 0; c < stations.length(); c++){
int departureA = schedule.lookup(trains.give(a).getId(), stations.give(c).getId(), 1);
int departureB = schedule.lookup(trains.give(b).getId(), stations.give(c).getId(), 1);
if(departureA == -1 || departureB == -1)
continue;
if(departureA < departureB){
for(int d = 0; d < trains.length(); d++){
int arrivalA = schedule.lookup(trains.give(a).getId(), stations.give(d).getId(), 0);
int arrivalB = schedule.lookup(trains.give(b).getId(), stations.give(d).getId(), 0);
if(arrivalA == -1 || arrivalB == -1)
continue;
if(arrivalA > departureA && arrivalB > departureB && arrivalB < arrivalA){
cout << "FOUND" << endl;
break;
}
}
}
}
}
}
}