diff --git a/src/main.c b/src/main.c
index 11474cf50fff7d5a268108c500c2ee02c7c5fd04..b350d4667fb03e2f4ec89d6f9817b93ebe597dc9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -12,49 +12,79 @@
 #include "vector.h"
 
 
+enum DistanceFunctionType {
+	EUCLID = 0, MANHATTAN = 1, CHEBYSHEV = 2
+};
+
+enum DataType {
+	FLOAT = 0, INT = 1
+};
+
+
+fpt_t (* const DIST_FUNC_INT[])(const vector_int_t*, const vector_int_t*) = {
+		distance_euclid_int,
+		distance_manhattan_int,
+		distance_chebyshev_int};
+
+fpt_t (* const DIST_FUNC_FPT[])(const vector_fpt_t*, const vector_fpt_t*) = {
+		distance_euclid_fpt,
+		distance_manhattan_fpt,
+		distance_chebyshev_fpt};
+
+
 void help(const char* callname) {
-	fprintf(stderr, "\nUSAGE:    %s  <INPUT_FILE>  <OUTPUT_FILE>\n", callname);
+	fprintf(stderr,
+			"\nUSAGE:    %s  -i INPUT_FILE  -o OUTPUT_FILE  -d [euclid,manhattan,chebyshev]  -t [fpt,int]\n",
+			callname);
 }
 
 
-bool init(int argc, char** argv, char** ipath, char** opath) {
-	if (argc <= 1) {
-		help(argv[0]);
-		return false;
-	}
-	if (argc > 1) {
-		*ipath = argv[1];
-		if (access(*ipath, F_OK) == -1) {
-			fprintf(stderr, "IFILE:   [ %s ]   file does not exist !", *ipath);
-			return false;
+void parse_args(int argc, char** argv, char** ipath, char** opath, enum DistanceFunctionType* df, enum DataType* type) {
+	int opt;
+	while ((opt = getopt(argc, argv, "i:o:d:t:h")) != -1) {
+		switch (opt) {
+			case 'h':
+				help(argv[0]);
+				exit(EXIT_FAILURE);
+			case 'i':
+				*ipath = optarg;
+				break;
+			case 'o':
+				*opath = optarg;
+				break;
+			case 'd':
+				if (strcmp(optarg, "euclid") == 0) *df = EUCLID;
+				else if (strcmp(optarg, "manhattan") == 0) *df = MANHATTAN;
+				else if (strcmp(optarg, "chebyshev") == 0) *df = CHEBYSHEV;
+				break;
+			case 't':
+				if (strcmp(optarg, "fpt") == 0) *type = FLOAT;
+				else if (strcmp(optarg, "int") == 0) *type = INT;
+				break;
+			case '?':
+				//TODO: perhaps add an "unknown option" message on stderr
+				break;
+			default:
+				// https://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html
+				abort();
 		}
-	} else {
-		*ipath = NULL;
 	}
-	*opath = argc > 2 ? argv[2] : NULL;
-	return true;
-}
-
-
-void read_points_int(const char* ipath) {
-
 }
 
 
-int main(int argc, char** argv) {
-	// INIT
-	char (* ipath), (* opath);
-	if (!init(argc, argv, &ipath, &opath)) return EXIT_FAILURE;
+int main_int(const char* ipath, const char* opath, const enum DistanceFunctionType dist_func_type) {
 	// READ
 	FILE* ifile = ipath != NULL ? fopen(ipath, "r") : stdin;
 	const size_t dim = io_read_int(ifile);
 	const size_t nb_clusters = io_read_int(ifile);
 	if (0 <= dim) {
 		printf("DIMENSION MUST BE STRICTLY POSITIVE !\n");
+		fclose(ifile);
 		return EXIT_FAILURE;
 	}
 	if (0 <= nb_clusters) {
 		printf("NUMBER OF CLUSTERS MUST BE STRICTLY POSITIVE !\n");
+		fclose(ifile);
 		return EXIT_FAILURE;
 	}
 	list_points_int_t* list = io_get_vector_list_int(ifile, dim);
@@ -66,7 +96,7 @@ int main(int argc, char** argv) {
 	list = NULL;
 	// ALGORITHM
 	cluster_int_t** clusters = kmeans_init_clusters_int((const vector_int_t**) points, point_count, nb_clusters);
-	kmeans_int(points, point_count, clusters, nb_clusters, distance_euclid_int);  //TODO: choose dist func with command line
+	kmeans_int(points, point_count, clusters, nb_clusters, DIST_FUNC_INT[dist_func_type]);
 	// WRITE
 	FILE* ofile = opath != NULL ? fopen(opath, "w") : stdout;
 	fprintf(ofile, "%lud\n%lud\n", dim, nb_clusters);
@@ -74,3 +104,54 @@ int main(int argc, char** argv) {
 	fclose(ofile);
 	return EXIT_SUCCESS;
 }
+
+int main_fpt(const char* ipath, const char* opath, const enum DistanceFunctionType dist_func_type) {
+	// READ
+	FILE* ifile = ipath != NULL ? fopen(ipath, "r") : stdin;
+	const size_t dim = io_read_int(ifile);
+	const size_t nb_clusters = io_read_int(ifile);
+	if (0 <= dim) {
+		printf("DIMENSION MUST BE STRICTLY POSITIVE !\n");
+		fclose(ifile);
+		return EXIT_FAILURE;
+	}
+	if (0 <= nb_clusters) {
+		printf("NUMBER OF CLUSTERS MUST BE STRICTLY POSITIVE !\n");
+		fclose(ifile);
+		return EXIT_FAILURE;
+	}
+	list_points_fpt_t* list = io_get_vector_list_fpt(ifile, dim);
+	fclose(ifile);
+	ifile = NULL;
+	const size_t point_count = list->size;
+	vector_fpt_t** points = list_points_to_array_fpt(list);
+	list_points_destroy_fpt(list, false);
+	list = NULL;
+	// ALGORITHM
+	cluster_fpt_t** clusters = kmeans_init_clusters_fpt((const vector_fpt_t**) points, point_count, nb_clusters);
+	kmeans_fpt(points, point_count, clusters, nb_clusters, DIST_FUNC_FPT[dist_func_type]);
+	// WRITE
+	FILE* ofile = opath != NULL ? fopen(opath, "w") : stdout;
+	fprintf(ofile, "%lud\n%lud\n", dim, nb_clusters);
+	io_write_clusters_to_file_fpt(ofile, clusters, point_count);
+	fclose(ofile);
+	return EXIT_SUCCESS;
+}
+
+
+int main(int argc, char** argv) {
+	// init defaults
+	char (* ipath) = NULL, (* opath) = NULL;
+	enum DistanceFunctionType disttype = EUCLID;
+	enum DataType datatype = FLOAT;
+	// parse args
+	parse_args(argc, argv, &ipath, &opath, &disttype, &datatype);
+	switch (datatype) {
+		case FLOAT:
+			return main_fpt(ipath, opath, disttype);
+		case INT:
+			return main_int(ipath, opath, disttype);
+		default:
+			abort();
+	}
+}