I've made a solution for a problem which involves changing order of objects having some mass, so it costs a mass of an object A and a mass of an object B to make a swap. The program needs to read a number of objects, their masses, their starting and ending order and calculate lowest cost of swapping objects to final order. The solution is correct in terms of calculations. The txt file has numbers in each line and name of a file is passed as command line argument. I would like to ask how should I split operations into separate functions and load data? What can I do to make a code cleaner? I am also wondering what exceptions should I made for invalid inputs?
#define min(a,b) ((a) < (b) ? (a) : (b))
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
void readFromFile(int argc, char* argv[],const int MAX_VERTEXES, const int MIN_VERTEXES, int &n, int &minWeightGlobally, std::vector<int> &weights, std::vector<int> &startingOrder, std::vector<int> &endingOrder)
{
std::ifstream file;
if (argc >= 2)
{
file.open(argv[1]);
}
else
{
throw std::exception("No parameter passed");
}
std::string line;
if (file.is_open())
{
for (int z = 0; z < 4; z++)
{
std::getline(file, line);
if (line.empty()) throw std::logic_error("Invalid input");
std::istringstream iss(line);
if (z == 0)
{
iss >> n;
if (n<MIN_VERTEXES || n>MAX_VERTEXES) throw std::exception("Invalid amount of vertices");
}
if (z == 1)
{
weights.reserve(n);
for (int a = 0; a < n; a++)
{
int d;
iss >> d;
weights.push_back(d);
minWeightGlobally = min(minWeightGlobally, weights[a]);
}
}
if (z == 2)
{
startingOrder.reserve(n);
for (int a = 0; a < n; a++)
{
int d;
iss >> d;
startingOrder.push_back(d - 1);
}
}
if (z == 3)
{
endingOrder.reserve(n);
for (int a = 0; a < n; a++)
{
int d;
iss >> d;
endingOrder.push_back(d - 1);
}
}
}
file.close();
}
else
{
throw std::exception("Unable to open file");
}
}
long long calculateLowestCostOfWork(int const &n, int const &MAX_WEIGHT, int const &minWeightGlobally, std::vector<int>& weights, std::vector<int>& startingOrder, std::vector<int>& endingOrder)
{
std::vector<int> permutation(n);
std::vector<bool> visitedVertexes(n);
long long result = 0;
//constructing permutation p
for (int i = 0; i < n; i++)
permutation[endingOrder[i]] = startingOrder[i];
for (int i = 0; i < n; i++)
{
int numberOfElementsInCycle = 0;
int minWeightInCycle = MAX_WEIGHT;
long sumOfWeightsInCycle = 0;
if (!visitedVertexes[i])
{
int x = i;
//decomposition for simple cycles and calculating parameters for each cycle
while (!visitedVertexes[x])
{
visitedVertexes[x] = true;
numberOfElementsInCycle++;
x = permutation[x];
sumOfWeightsInCycle += weights[x];
minWeightInCycle = min(minWeightInCycle, weights[x]);
}
//calculating lowest cost for each cycle
result += (long long)min((sumOfWeightsInCycle + (numberOfElementsInCycle - 2) * minWeightInCycle), (sumOfWeightsInCycle + minWeightInCycle + (numberOfElementsInCycle + 1) * minWeightGlobally));
}
}
return result;
}
int main(int argc, char *argv[])
{
const int MAX_WEIGHT = 6500, MAX_VERTEXES = 1000000, MIN_VERTEXES = 2;
std::vector<int> weights, startingOrder, endingOrder;
int n=0;
int minWeightGlobally = MAX_WEIGHT;
try
{
readFromFile(argc, argv,MAX_VERTEXES, MIN_VERTEXES, n, minWeightGlobally, weights, startingOrder, endingOrder);
}
catch (...)
{
std::cout << "Error";
}
std::cout << calculateLowestCostOfWork(n,MAX_WEIGHT,minWeightGlobally,weights,startingOrder,endingOrder);
return 0;
}
The input file is in form like below, first line (int n in code) it's telling about amount of objects (that's a nice name to include). Second line has their weights, third line startingOrder and last endingOrder. The task is to calculate a cost of move of objects(a cost is defined by sum of weights of two objects that are moved) from starting to ending order.
8 197 170 124 180 128 163 188 140 2 5 7 8 1 3 6 4 5 6 1 8 2 4 7 3
So ideally there should be exactly as many numbers in each row in each vector as in first line. The worst case scenario is obviously no values in any line after first line, so we will move through undeclared memory or out of bounds and we will get out of bounds exception. In the other cases program could calculate something, although there is a little possibility that it will calculate something good e.g input like this is valid e.g
8 197 170 124 180 128 163 188 140 1 2 3 3 1 2
is valid, but obviously it should calculate for 8 numbers, not for only three.
long long functionName
does ? \$\endgroup\$long long functionName
. I haven't seen something similar. \$\endgroup\$