Files
427f5252-gr04-repo/Projekt/main.cpp
2023-02-23 13:24:57 +01:00

158 lines
5.2 KiB
C++

/***
* 13. Kurier ma za zadanie zawieść towar do klientów w różnych lokalizacjach i powrócić do miejsca, z którego wyjechał. Kurier musi odwiedzić każdego klienta raz i tylko raz. Należy
znaleźć zamkniętą najkrótszą drogę, która umożliwia odwiedzenie wszystkich klientów.
W pliku wejściowym zapisane są długości dróg pomiędzy miastami. Drogi zapisane
są w następujący sposób:
(<klient A> - <klient B> : <odległość>).
Niektóre drogi nie są symetryczne, tzn. jest pewna różnica między drogą tam a z powrotem.
Zapis (<klient C> -> <klient D> : <odległość CD>), oznacza długość drogi jednokierunkowej
od klienta C do klienta D. Poszczególne drogi są rozdzielone przecinkami. Nie jest podana
liczba dróg. Jeżeli nie jest możliwe wyznaczenie drogi, program zgłasza odpowiedni
komunikat. Przykładowy plik wejściowy:
(1 - 2 : 4.5), (4 -> 3 : 4.5), (4 - 2 : 0.4)
W pliku wynikowym należy zapisać drogę kuriera (kolejność odwiedzania klientów i długość
drogi).
Program uruchamiany jest z linii poleceń z potrzebnymi przełącznikami, natomiast
uruchomienie programu bez parametrów powoduje wypisanie krótkiej instrukcji
1 2 3 4
1 4.5
2 4.5 0.4
3 4.5
4 0.4
**/
#include <iostream>
#include <iomanip>
#include <string>
#include "include/cxxopts.hpp"
#include "include/types.hpp"
#include <algorithm>
#include <limits.h>
#include <queue>
#include <fstream>
#include <sstream>
double nieskończoność=std::numeric_limits<double>::max();
using namespace std;
cxxopts::Options options("Kurier", "Program rozwiązujący problem kuriera");
/*
*
* Parsujemy A, B, rodzaj korelacji <bool>, dystans
*
*
*/
typedef std::map<std::string, std::map<std::string, double>> mapa;
mapa mapaOdległości;
/*
* @brief Funkcja czyszcząca stringi z niepotrzebnych znaków
*/
void czyscStringa( string &str, char* znakiDoCzyszczenia ) {
for ( unsigned int i = 0; i < strlen(znakiDoCzyszczenia); ++i ) {
str.erase( remove(str.begin(), str.end(), znakiDoCzyszczenia[i]), str.end() );
}
}
void dijkstruj(mapa doPrzetworzenia){
double punktStartowy = doPrzetworzenia[0][0];
for (auto i = doPrzetworzenia.begin(); i != doPrzetworzenia.end(); i++) {
for (auto ii = i->second.begin(); ii != i->second.end(); ii++) {
std::cout<< i->first << ii->first << ii->second << std::endl;
}
}
}
void dumpOutput(string outputFile, string preparedString)
{
ofstream file(outputFile);
file << preparedString;
}
/**
* @brief Funkcja parsująca dane wejściowe.
*
* @details Funkcja pobiera dane wejściowe z przekazanej ścieżki do pliku. Plik zawiera długości dróg pomiędzy poszczególnymi miastami w formacie (<klient A> - <klient B> : <odległość>).
*
* @param inputFile Ścieżka do pliku wejściowego
*
* @return iterator pliku
*/
void parseInput(string inputFile) {
ifstream file(inputFile);
std::string token,miastoA,miastoB,dystans,rodzajRelacji;
while(std::getline(file, token, ',')) {
czyscStringa(token, "(:)");
istringstream tokenstream(token);
tokenstream >> miastoA >> rodzajRelacji >> miastoB >> dystans;
if (rodzajRelacji.compare("-")==0) {
// Jeśli drugie miasto zaczyna się od znaku '-', to znaczy, że jest to droga dwukierunkowa.
// Dodajemy odległość do mapy dla obu kierunków.
mapaOdległości[miastoA][miastoB] = stod(dystans);
mapaOdległości[miastoB][miastoA] = stod(dystans);
} else if (rodzajRelacji.compare("->")==0) {
// Jeśli drugie miasto zaczyna się od znaku '>', to znaczy, że jest to droga jednokierunkowa.
// Dodajemy odległość tylko w jednym kierunku.
mapaOdległości[miastoA][miastoB] = stod(dystans);
mapaOdległości[miastoB][miastoA] = nieskończoność;
}
}
}
/**
* @brief Główna funkcja.
*
*/
int main (int argc, char *argv[])
{
options.add_options()
("d,debug", "Włącza tryb debugowania") // a bool parameter
("h,help", "Pokazuje pomoc") // a bool parameter
("i,input", "Nazwa pliku wejściowego", cxxopts::value<string>())
("o,output", "Nazwa pliku wyjściowego", cxxopts::value<string>())
("v,verbose", "Pokazuje tok działania programu", cxxopts::value<bool>()->default_value("false"));
auto result = options.parse(argc, argv);
// Jeżeli przełącznik -h jest ustawiony albo nie podano argumetów, wyświetla pomoc.
if (result.count("help") || argc == 1) {
std::cout << options.help() << std::endl;
exit(0);
}
bool debug = result["debug"].as<bool>();
string plikWejsciowy;
string plikWyjsciowy;
if (result.count("input") && result.count("output")) {
plikWejsciowy = result["input"].as<string>();
parseInput(plikWejsciowy);
dijkstruj(mapaOdległości);
plikWyjsciowy = result["output"].as<string>();
} else {
std::cout << std::endl << "Błąd - nie podano wymaganych parametrów" << std::endl << std::endl << std::endl << options.help() << std::endl;
exit(3);
}
if (debug == true) {
for (int i = 0; i < argc; i++) {
std::cout << argv[i] << std::endl;
}
}
exit(0);
}