/*
Simple I/O "Assignment"
The "assignment":
1. Load a file of arbitrary length that is composed of 3 tab-separated columns
with floating point numbers representing x, y, z coordinates of points. Lines
starting with the pound character (i.e. #) are comments and your program
should ignore them.
2. Accept file on the command lines:
$ ./a.out some_data.dat
3. Use STL sort to sort all data points beyond the first by their distance from
the first data point (shortest to longest).
4. Output sorted list as x y z distance use only 4 significant figures (output
only once we can compare speed and correctness with a script later).
5. (bonus) Implement your own sorting method and compare to STL method.
6. (bonus) Try some of the Boost libraries
7. (bonus) Accept command line arguments to pick algorithm, sort order, data
points. Try Boost Program Options
C++ suggestions:
1. Write a C++ class (or struct) that represents a vector (you can templatize it
on a constant to make it N dimensional yet relatively efficient)
2. Overload >> input operator to read things from the file in a more idiomatic
way
3. Overload << output operator to print things from the file in a more idiomatic
way
4. Use an STL container to store loaded vectors. You can probably pull it off by
dynamically growing your own arrays, or maybe reading the file twice but the
STL stuff will work better and it's easier.
Warning
C++ has a datatype called vector, this is a dynamic list not a mathematical
vector.
5. Look at the pow(x) routine in the boost math library (under
special_functions).
Oh and I suggest sticking to the standard libraries (STL and Python)... if you
decide to use stuff from Boost and numpy it would probably be good to implement
your own too and compare them.
*/
#include
#include
#include
#include
#include
using namespace std;
struct Point
{
float x, y, z, r;
int use_default;
};
struct dist_compare
{
bool operator() (Point const& a, Point const& b) {
return a.r < b.r;
}
};
int set_options(int argc, char* argv[], Point& p0)
{
vector args (argv + 2, argv + argc);
p0.use_default = 1;
for (int i = 0; i < args.size(); i++) {
if (args[i] == "-xyz") {
istringstream sstream (args[i+1] + " " + args[i+2] + " " + args[i+3]);
sstream >> p0.x;
sstream >> p0.y;
sstream >> p0.z;
p0.use_default = 0;
}
}
return 0;
}
int get_coords(ifstream &fstream, vector& p_list)
{/*
Build up a vector (of point objects) from x,y,z values in the given file.
Empty lines and lines starting with # are ignored.
*/
float val;
string line;
Point p;
while (fstream.good()) {
getline(fstream, line);
// Skip empty lines or lines that start with #
if (line == "" || line[0] == '#') {
continue;
}
// Get floats from the line string, make the point, add to vector
istringstream sstream (line);
sstream >> p.x;
sstream >> p.y;
sstream >> p.z;
p_list.push_back(p);
}
return 0;
}
int calc_dist(vector& p_list, Point& p0)
{
if (p0.use_default == 1) {
p0.x = p_list[0].x;
p0.y = p_list[0].y;
p0.z = p_list[0].z;
}
for (int i = 0; i < p_list.size(); i++) {
p_list[i].r = sqrt(pow(p_list[i].x - p0.x, 2) +
pow(p_list[i].y - p0.y, 2) +
pow(p_list[i].z - p0.z, 2));
}
return 0;
}
int dist_sort(vector& p_list)
{
sort(p_list.begin(), p_list.end(), dist_compare());
return 0;
}
int pretty_print(vector& p_list)
{
for (int i = 0; i < p_list.size(); i++) {
printf("%.4f\t%.4f\t%.4f\t%.4f\n",
p_list[i].x, p_list[i].y, p_list[i].z, p_list[i].r);
}
}
int main (int argc, char* argv[])
{
string filename = argv[1];
Point p0;
set_options(argc, argv, p0);
// Build the point list
vector p_list;
ifstream fstream (filename.c_str());
get_coords(fstream, p_list);
fstream.close();
// Calculate distances
calc_dist(p_list, p0);
// Sort the points based on distances
dist_sort(p_list);
// Print the point coords and distances
pretty_print(p_list);
return 0;
}