diff --git a/src/Graphe.cpp b/src/Graphe.cpp index a139229..5f2a481 100644 --- a/src/Graphe.cpp +++ b/src/Graphe.cpp @@ -1,60 +1,55 @@ #include "Graphe.h" +#include "PrettyPrint.h" +#include +#include #include #include -#include +#include +#include +#include using namespace std; - -std::ostream& operator<<(std::ostream& os, const Graphe& g) { - os << "Graphe: " << g.file_name << "\n"; - os << "Comment: " << g.comment << "\n"; - os << "Directed: " << (g.directed ? "true" : "false") << "\n"; - os << "Number of vertices: " << g.nb_vertices << "\n"; - os << "Number of edges: " << g.nb_edges << "\n"; - os << "Vertices:\n"; - for (const auto& vertex : g.m_Vertecies) { - os << " ID: " << vertex.m_Name << ", Values: " << vertex.m_Values << "\n"; - } - os << "Edges:\n"; - for (const auto& edge : g.m_Edges) { - os << " Start: " << edge.m_Start->m_Name << ", End: " << edge.m_End->m_Name << ", Values: " << edge.m_Values << "\n"; - } - return os; +void debug(string s) { + cout << s << endl; } Graphe::Graphe(const string& fileName) { + auto startTime = chrono::high_resolution_clock::now(); + ifstream file(fileName); if (!file.is_open()) { - // cerr << "Error opening file: " << fileName << endl; + cerr << "Error opening file: " << fileName << endl; return; } + + string fileContents; + string line; bool isSettingsSection = true; bool verticesSection = false; bool edgesSection = false; - while (getline(file, line)) { + istringstream fileStream((string())); + istream& inputStream = static_cast(file); + + // Settings + while (getline(inputStream, line)) { if (line.empty()) { if (isSettingsSection) { isSettingsSection = false; verticesSection = true; - // cout << "Settings section ended, now reading vertices." << endl; - continue; - } - if (verticesSection) { - verticesSection = false; - edgesSection = true; - // cout << "Vertices section ended, now reading edges." << endl; - continue; + break; } } + if (isSettingsSection) { - // cout << "Settings :" << line << endl; - regex settingRegex(R"(^([A-Z_]+):\s([\w\d\.]+)$)"); - smatch match; - if (regex_match(line, match, settingRegex)) { - string key = match[1].str(); - string value = match[2].str(); + size_t colonPos = line.find(':'); + if (colonPos != string::npos) { + string key = line.substr(0, colonPos); + string value = line.substr(colonPos + 1); + + value.erase(0, value.find_first_not_of(" \t")); + if (key == "NAME") { file_name = value; } else if (key == "COMMENT") { @@ -63,79 +58,113 @@ Graphe::Graphe(const string& fileName) { directed = (value == "true"); } else if (key == "NB_VERTICES") { nb_vertices = stoi(value); - m_Vertecies.reserve(nb_vertices); } else if (key == "NB_EDGES") { nb_edges = stoi(value); - m_Edges.reserve(nb_edges); } else if (key == "NB_VALUES_BY_VERTEX") { nb_values_by_vertex = stoi(value); } else if (key == "NB_VALUES_BY_EDGE") { nb_values_by_edge = stoi(value); - } else { - cerr << "Unknown setting: " << key << endl; } } } + } + m_Vertecies.reserve(nb_vertices); + m_Edges.reserve(directed ? nb_edges : 2 * nb_edges); - if (verticesSection) { - // cout << "Reading vertices : " << line << endl; - if (line.size() >= 3 && line.substr(0, 3) == "VER") { - continue; - } - regex vertexRegex(R"(^(\d+)\s(\w+)\s?(.*)$)"); - smatch match; - if (regex_match(line, match, vertexRegex)) { - Vertex v; - int id = stoi(match[1].str()); - v.m_Name = match[2].str(); - string valuesStr = match[3].str(); - regex valueRegex(R"((\d+))"); - auto valuesBegin = sregex_iterator(valuesStr.begin(), valuesStr.end(), valueRegex); - auto valuesEnd = sregex_iterator(); - for (sregex_iterator i = valuesBegin; i != valuesEnd; ++i) { - v.m_Values.push_back(stof((*i).str())); - } - - m_Vertecies.push_back(v); - m_VertexMap[v.m_Name] = &m_Vertecies[id]; - } else { - cerr << "Invalid vertex line: " << line << endl; - } + // Vertices + int vertexCounter = 0; + while (getline(inputStream, line) && verticesSection) { + if (line.empty()) { + verticesSection = false; + edgesSection = true; + break; } - if (edgesSection) { - // cout << "Reading edges : " << line << endl; - if (line.size() >= 3 && line.substr(0, 3) == "EDG") { - continue; + + if (line.size() >= 3 && line.substr(0, 3) == "VER") { + continue; + } + + istringstream iss(line); + int id; + string name; + if (iss >> id >> name) { + Vertex v; + v.m_Name = name; + + float value; + while (iss >> value) { + v.m_Values.push_back(value); } - regex edgeRegex(R"(^(\d+)\s(\d+)\s?(.*)$)"); - smatch match; - if (regex_match(line, match, edgeRegex)) { + + m_Vertecies.push_back(v); + m_VertexMap[v.m_Name] = &m_Vertecies.back(); + vertexCounter++; + } + } + + // Edges + while (getline(inputStream, line) && edgesSection) { + if (line.size() >= 3 && line.substr(0, 3) == "EDG") { + continue; + } + + istringstream iss(line); + unsigned int startId, endId; + if (iss >> startId >> endId) { + if (startId >= 0 && startId < m_Vertecies.size() && endId >= 0 && endId < m_Vertecies.size()) { + Edge e; - e.m_Start = &m_Vertecies[stoi(match[1].str())]; - e.m_End = &m_Vertecies[stoi(match[2].str())]; - string valuesStr = match[3].str(); - regex valueRegex(R"((\d+))"); - auto valuesBegin = sregex_iterator(valuesStr.begin(), valuesStr.end(), valueRegex); - auto valuesEnd = sregex_iterator(); - for (sregex_iterator i = valuesBegin; i != valuesEnd; ++i) { - e.m_Values.push_back(stof((*i).str())); + e.m_Start = &m_Vertecies[startId]; + e.m_End = &m_Vertecies[endId]; + + float value; + while (iss >> value) { + e.m_Values.push_back(value); } - std::size_t edgeID = m_Edges.size(); + size_t edgeId = m_Edges.size(); m_Edges.push_back(e); - e.m_Start->m_Edges.push_back(&m_Edges[edgeID]); + + m_Vertecies[startId].m_Edges.push_back(&m_Edges[edgeId]); + if (!directed) { Edge reverseEdge; reverseEdge.m_Start = e.m_End; reverseEdge.m_End = e.m_Start; reverseEdge.m_Values = e.m_Values; - std::size_t index = m_Edges.size(); + + size_t reverseEdgeId = m_Edges.size(); m_Edges.push_back(reverseEdge); - reverseEdge.m_Start->m_Edges.push_back(&m_Edges[index]); + m_Vertecies[endId].m_Edges.push_back(&m_Edges[reverseEdgeId]); } } else { - cerr << "Invalid edge line: " << line << endl; + cerr << "Invalid vertex IDs in edge: " << startId << " -> " << endId << endl; } } } + + auto elapsed = std::round(chrono::duration(chrono::high_resolution_clock::now() - startTime).count() * 1000); + debug("File: " + PrettyPrint::format(file_name, Color::Blue)); + debug("Graph loaded in " + + PrettyPrint::format(to_string(static_cast(elapsed)) + "ms", elapsed < 1000 ? Color::Green : Color::Yellow)); + debug("Loaded " + PrettyPrint::format(to_string(m_Vertecies.size()), Color::Green) + " vertices and " + + PrettyPrint::format(to_string(m_Edges.size()), Color::Green) + " edges"); +} + +// The stream operator implementation remains unchanged +std::ostream& operator<<(std::ostream& os, const Graphe& g) { + os << "Graphe: " << PrettyPrint::format(g.file_name, Color::Blue) << "\n"; + os << "Comment: " << PrettyPrint::format(g.comment, Color::Cyan) << "\n"; + os << "Directed: " << (g.directed ? PrettyPrint::format("true", Color::Green) : PrettyPrint::format("false", Color::Red)) << "\n"; + os << "Number of vertices: " << PrettyPrint::format(g.nb_vertices, Color::Magenta) << "\n"; + os << "Number of edges: " << PrettyPrint::format(g.nb_edges, Color::Magenta) << "\n"; + os << "Vertices:\n"; + for (const auto& vertex : g.m_Vertecies) { + os << " Name: " << vertex.m_Name << ", Values: " << vertex.m_Values << "\n"; + } + os << "Edges:\n"; + for (const auto& edge : g.m_Edges) { + os << " Start: " << edge.m_Start->m_Name << ", End: " << edge.m_End->m_Name << ", Values: " << edge.m_Values << "\n"; + } + return os; } diff --git a/src/PrettyPrint.cpp b/src/PrettyPrint.cpp new file mode 100644 index 0000000..80b65b0 --- /dev/null +++ b/src/PrettyPrint.cpp @@ -0,0 +1,42 @@ +#include "PrettyPrint.h" +#include +#include + +void PrettyPrint::print(const std::string& str, Color c) { + std::cout << format(str, c) << std::endl; +} + +std::string PrettyPrint::format(const std::string& str, Color c) { + std::string colorCode; + switch (c) { + case Color::Red: + colorCode = "\033[31m"; + break; + case Color::Green: + colorCode = "\033[32m"; + break; + case Color::Blue: + colorCode = "\033[34m"; + break; + case Color::Yellow: + colorCode = "\033[33m"; + break; + case Color::Magenta: + colorCode = "\033[35m"; + break; + case Color::Cyan: + colorCode = "\033[36m"; + break; + case Color::White: + colorCode = "\033[37m"; + break; + case Color::Black: + colorCode = "\033[30m"; + break; + } + return colorCode + str + "\033[0m"; +} + +std::string PrettyPrint::format(int value, Color c) { + return format(std::to_string(value), c); +} diff --git a/src/PrettyPrint.h b/src/PrettyPrint.h index 7855eff..745c897 100644 --- a/src/PrettyPrint.h +++ b/src/PrettyPrint.h @@ -1,15 +1,12 @@ #pragma once #include +#include -inline void printYellow(const std::string& text) { - std::cout << "\033[33m" << text << "\033[0m"; -} -inline void printRed(const std::string& text) { - std::cout << "\033[31m" << text << "\033[0m"; -} -inline void printGreen(const std::string& text) { - std::cout << "\033[32m" << text << "\033[0m"; -} -inline void printBlue(const std::string& text) { - std::cout << "\033[34m" << text << "\033[0m"; -} +enum class Color { Red, Green, Blue, Yellow, Magenta, Cyan, White, Black }; + +class PrettyPrint { + public: + static void print(const std::string& str, Color c); + static std::string format(const std::string& str, Color c); + static std::string format(int value, Color c); +}; diff --git a/src/main.cpp b/src/main.cpp index dbe12eb..cdf98f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,38 +1,35 @@ #include "Algo.h" #include "Graphe.h" -#include #include #include int main(int argc, char** argv) { - auto start = std::chrono::high_resolution_clock::now(); - Graphe graphe("graphe-communes.gra"); - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(end - start).count(); - std::cout << "Temps de chargement du graphe : " << duration << " ms.\n"; - // std::cout << graphe << std::endl; - // auto result = PlusCourtCheminNbArcs(graphe, graphe.getVertex("a")); + std::string tab_graphes[4] = { + "graphe-oriente-01.gra", "graphe-nonoriente-01.gra", "graphe-communes.gra", "cours-representation.gra"}; + Graphe graphe(tab_graphes[3]); + std::cout << graphe << std::endl; + auto result = PlusCourtCheminNbArcs(graphe, graphe.getVertex("a")); - // std::cout << "Résultat :\n"; - // for (auto& [vertex, longueur] : result) { - // std::cout << vertex->m_Name << " " << longueur << "\n"; - // } + std::cout << "Résultat :\n"; + for (auto& [vertex, longueur] : result) { + std::cout << vertex->m_Name << " " << longueur << "\n"; + } - // auto result2 = PlusCourtCheminsNbArcs(graphe, graphe.getVertex("a")); + auto result2 = PlusCourtCheminsNbArcs(graphe, graphe.getVertex("a")); - // std::cout << "Résultat :\n"; - // for (auto& [vertex, chemin] : result2) { - // std::cout << vertex->m_Name << " " << chemin << "\n"; - // } + std::cout << "Résultat :\n"; + for (auto& [vertex, chemin] : result2) { + std::cout << vertex->m_Name << " " << chemin << "\n"; + } - // auto result3 = PlusCourtChemin(graphe, graphe.getVertex("a"), graphe.getVertex("e")); + auto result3 = PlusCourtChemin(graphe, graphe.getVertex("a"), graphe.getVertex("e")); - // std::cout << "Résultat :\n"; - // std::cout << result3 << std::endl; + std::cout << "Résultat :\n"; + std::cout << result3 << std::endl; - // auto result4 = PlusCourtCheminDjikstra(graphe, graphe.getVertex("a")); - // std::cout << "Résultat :\n"; - // for (auto& [vertex, longueur] : result4) { - // std::cout << vertex->m_Name << " " << longueur << "\n"; - // } + auto result4 = PlusCourtCheminDjikstra(graphe, graphe.getVertex("a")); + std::cout << "Résultat :\n"; + for (auto& [vertex, longueur] : result4) { + std::cout << vertex->m_Name << " " << longueur << "\n"; + } }