// Helper function that writes down the train car IDs into a vector, // to allow faster calculation of link/unlink/shift costs std::vector<int> RecordIDs(TrainCar* t1) { std::vector<int> answer; TrainCar* tmp = t1; // loop over all the train cars and store the car IDs in a vector while (tmp != NULL) { answer.push_back(tmp->getID()); tmp = tmp->next; } return answer; }
// Returns a pointer to the final car of a given type in a train. // Returns NULL if there is no car of given type. TrainCar* Train::getFinalCarOfType(TrainCar::cType type){ TrainCar* nodeOn = m_head; TrainCar* lastOfType = NULL; while(nodeOn->m_next != NULL) { if(nodeOn->getType() == type) { lastOfType = nodeOn; } nodeOn = nodeOn->m_next; } return lastOfType; }
// Returns a pointer to the Nth car of a given type in the train. // Returns NULL if no car of that type or number appears in the train. // Count starts at 1. TrainCar* Train::getNthCarOfType(TrainCar::cType type, int n) { TrainCar* nodeOn = m_head; TrainCar* nthCar = NULL; // The number of cars of a given type found. int foundSoFar = 0; while(nodeOn->m_next != NULL && nthCar == NULL) { if(nodeOn->getType() == type) { foundSoFar++; } if(foundSoFar == n) { nthCar = nodeOn; } nodeOn = nodeOn->m_next; } return nthCar; }
void SimpleTrainTest() { std::cout << "============================================================================" << std::endl; std::cout << "SIMPLE TRAIN TEST" << std::endl; // create a train with 6 dynamically-allocated cars in a doubly-linked list structure TrainCar* simple = NULL; PushBack(simple, TrainCar::MakeEngine()); PushBack(simple, TrainCar::MakePassengerCar()); PushBack(simple, TrainCar::MakePassengerCar()); PushBack(simple, TrainCar::MakeDiningCar()); PushBack(simple, TrainCar::MakePassengerCar()); PushBack(simple, TrainCar::MakeSleepingCar()); // inspect the cars, the links, the links, and sequential IDs... assert (simple->isEngine()); assert (simple->prev == NULL); assert (simple->next->isPassengerCar()); assert (simple->next->prev->isEngine()); assert (simple->next->next->isPassengerCar()); assert (simple->next->next->next->isDiningCar()); assert (simple->next->next->next->next->isPassengerCar()); assert (simple->next->next->next->next->next->isSleepingCar()); assert (simple->next->next->next->next->next->next == NULL); assert (simple->next->getID() == simple->getID()+1); assert (simple->next->next->getID() == simple->next->getID()+1); assert (simple->next->next->next->getID() == simple->next->next->getID()+1); assert (simple->next->next->next->next->getID() == simple->next->next->next->getID()+1); assert (simple->next->next->next->next->next->getID() == simple->next->next->next->next->getID()+1); // helper routine sanity check & print the results SanityCheck(simple); PrintTrain(simple); // fully delete all TrainCar nodes to prevent a memory leak DeleteAllCars(simple); }
void Separate(TrainCar* &train1,TrainCar* &train2,TrainCar* &train3){ int num = Calculate_numcars_apart_from_engines(train1); int num_of_engine = Calculate_num_of_engines(train1); int num_trains = 2; int ideal_engine_first_car = num_of_engine / num_trains; assert(ideal_engine_first_car != 0); float temp_num_of_engine = num_of_engine; //--------------------------------------------------------------------------- // Rounded to the closest integer: int num_nonengine_cars = num * (ideal_engine_first_car / temp_num_of_engine); float temp_stata = num * (ideal_engine_first_car / temp_num_of_engine); if ((temp_stata - num_nonengine_cars) > 0.5 ) { num_nonengine_cars += 1; } assert(num_nonengine_cars != 0); // Try to find the optimal situation, if this situation exists, we just need to cut one time // in the middle. //--------------------------------------------------------------------------------------- int alternative_noengine_cars = num - num_nonengine_cars; int alternative_engines = num_of_engine - ideal_engine_first_car; bool found_optimal_solution = false; int count_cars = 0; int count_engines = 0; while (train1->next != NULL) { if (train1->isEngine()) { count_engines++; } else { count_cars ++; } if ((count_engines == ideal_engine_first_car && count_cars == num_nonengine_cars) || (count_engines == alternative_engines && count_cars == alternative_noengine_cars)) { // If the optimal conditions meet, we can just break one time in the middle: train2 = train1; train3 = train1->next; train2->next = NULL; train3->prev = NULL; while (train2->prev != NULL) { train2 = train2->prev; } found_optimal_solution = true; } if (!found_optimal_solution) { train1 = train1->next; } } if (found_optimal_solution) { train1 = train1->next; } else { while (train1 ->prev != NULL) { train1 = train1->prev; } } //------------------------------------------------------------------------------------ // If we didn' t find the optimal situation: then use normal way: if (! found_optimal_solution) { //--------------------------------------------------------------------------- // Generally, I use the nonengine car number to calculate. // Since there are only two trains, we just need to separate engines and cars into two trains. // If they are not equal, I just try to get one more car in one side. // My logic is first calculate the optimal number of engines. When the nonengine car number hits // the ideal number, the engine number may be bigger, equal or smaller // 1) if it is equal, just break in the middle // 2) if it is smaller, just go to the other side, everytime I hits an engine, remove it and insert // to the previous train. // 3) if it is bigger, reverse // Since I have consider the optimal situation before, I don't need to consider here. int count = 0; int count_engine = 0; while (train1 != NULL) { if (! train1->isEngine()) { count ++; } else { count_engine++; } if (count == num_nonengine_cars) { // There are three situations: // If the number of engines of the first train is equal to the ideal engines number: //--------------------------------------------------------------------------------- if (count_engine == ideal_engine_first_car) { train2 = train1; train3 = train1->next; train3->prev = NULL; train2->next = NULL; // Go back to the head while (train2->prev!= NULL) { train2 = train2->prev; } while (train1->next != NULL) { train1 = train1->next; } } else if (count_engine < ideal_engine_first_car){ // count_engine > ideal_engine_first_car //-------------------------------------------- train2 = train1; // Go back to the head while (train2->prev!= NULL) { train2 = train2->prev; } //----------------------------------- int needed_engines = ideal_engine_first_car - count_engine; int specialcounter = 0; int i =0; TrainCar* temp = train1; while (i < needed_engines) { temp = temp->next; if (temp->isEngine()) {i ++;} specialcounter++; } //------------------------------------ if (i == specialcounter) { // Special case train3 = temp->next; temp->next = NULL; train3->prev = NULL; } else { TrainCar* p = train1->next; train1->next = NULL;// train1 keep track of the ending car of the first train p->prev = NULL; train3 = p; // Make train3 to the first nonengine car while (train3->isEngine()) { train3 = train3->next; } TrainCar* q = p; i = 0; while (i < needed_engines) { q = p->next; if (p->isEngine()) { remove_cars(p); insert_cars_prev(train1, p); train1 = train1->next; i ++; } p = q; } while (train3->prev != NULL) { train3 = train3->prev; } } while (train1->next != NULL) { train1 = train1->next; } } else { // count_engine > ideal_engine_first_car //------------------------------------------------------------------------ train2 = train1; // Go back to the head while (train2->prev!= NULL) { train2 = train2->prev; } //----------------------------------- train1 = train1->next; TrainCar* temp = train1; int needed_engines = count_engine - ideal_engine_first_car; int specialcounter = 0; int i =0; while (i < needed_engines) { temp = temp->prev; if (temp->isEngine()) {i ++;} specialcounter++; } //------------------------------------------ if (i == specialcounter) { // Special case train3 = temp; TrainCar* temp1 = temp->prev; train3->prev = NULL; temp1->next = NULL; } else { train3 = temp; TrainCar* p =train1->prev; train1->prev = NULL; p->next = NULL; TrainCar* q = p; i = 0; while (i < needed_engines) { q = p->prev; if (p->isEngine()) { remove_cars(p); insert_cars_next(train1, p); train1 = train1->prev; i ++; } p = q; } while (train3->prev != NULL) { train3 = train3->prev; } } while (train1->next != NULL) { train1 = train1->next; } } } train1 = train1->next; } } }