diff --git a/CMakeLists.txt b/CMakeLists.txt index dbdfaa3..de22f4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_CXX_STANDARD 17) file(GLOB SOURCES "src/*.cpp") add_executable(simulator main.cpp ${SOURCES}) +add_executable(test graphMat/test.cxx) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) @@ -13,3 +14,4 @@ target_link_libraries(simulator PRIVATE Threads::Threads) target_include_directories(simulator PRIVATE includes) target_include_directories(simulator PRIVATE .) +target_include_directories(test PRIVATE .) diff --git a/LICENSE b/LICENSE index 014d46e..dad8552 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2020 Aditya Gupta - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2020 Aditya Gupta + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/graphMat/.vscode/c_cpp_properties.json b/graphMat/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..8fb34ba --- /dev/null +++ b/graphMat/.vscode/c_cpp_properties.json @@ -0,0 +1,20 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.18362.0", + "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe", + "cStandard": "c11", + "intelliSenseMode": "msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/graphMat/.vscode/launch.json b/graphMat/.vscode/launch.json index e32ad6a..424c9c5 100644 --- a/graphMat/.vscode/launch.json +++ b/graphMat/.vscode/launch.json @@ -1,20 +1,20 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "cl.exe - Build and debug active file", - "type": "cppvsdbg", - "request": "launch", - "program": "${workspaceFolder}\\test.exe", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "preLaunchTask": "C/C++: cl.exe build active file" - } - ] +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "cl.exe - Build and debug active file", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceFolder}\\test.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": true, + "preLaunchTask": "C/C++: cl.exe build active file" + } + ] } \ No newline at end of file diff --git a/graphMat/.vscode/settings.json b/graphMat/.vscode/settings.json index cdfe37c..aab9951 100644 --- a/graphMat/.vscode/settings.json +++ b/graphMat/.vscode/settings.json @@ -6,8 +6,17 @@ "new": "cpp", "numeric": "cpp", "system_error": "cpp", - "ostream": "cpp" + "ostream": "cpp", + "list": "cpp", + "vector": "cpp", + "xlocnum": "cpp", + "xstring": "cpp", + "iosfwd": "cpp" }, + "C_Cpp.default.includePath": [ + "${default}", + "${workspaceFolder}/.." + ], "workbench.colorCustomizations": { "activityBar.background": "#551B00", "titleBar.activeBackground": "#772600", diff --git a/graphMat/.vscode/tasks.json b/graphMat/.vscode/tasks.json index 28d05dc..3b24918 100644 --- a/graphMat/.vscode/tasks.json +++ b/graphMat/.vscode/tasks.json @@ -26,6 +26,8 @@ "args": [ "/Zi", "/EHsc", + "/std:c++latest", + "/I..", "/Fe:", "${workspaceFolder}\\test.exe", "${workspaceFolder}\\test.cxx" diff --git a/graphMat/README.md b/graphMat/README.md index f6d49c3..d44475a 100644 --- a/graphMat/README.md +++ b/graphMat/README.md @@ -1,21 +1,21 @@ -# Matrix as a Graph ----- - -The title mostly says it, i will complete it more as needed by the main project -This is a subproject for the worldline project (a catchy name, but an interesting small simulator for me) - -## Purpose - - -I needed a matrix like data structure, that can have -1. expansion and deletetion capabilities like that of a list (ie. no need to copy again and again for expansion as in std::vector (and i am not talking about the capacity vs size here, that would not work for my purpose)) - -2. access as a vector 2x2 matrix, or atleast fast access - -Then, i had read somewhere, _A matrix is inherently a graph, each node connected to 4 adjacent nodes_, though it maybe very simple, but quite intutive it seems. - -So, now the point of it, So i created a matrix data structure, based on a graph, that completes the requirements for `point 1 above`, though it doesn't have constant time lookups like std::vector, but for my case, i chose to create it like this. - -## Probable Uses - - -It will likely be used as the `world plot`, since think, this world will be expanding (continuosly or on need basis, so I didn't wanted `vector`, that had been quite an overhead for expansion like 40\*40 to 100\*100) -Also, in case of `vector`, you will likely have it grow in ONLY TWO DIRECTIONS, and I WANTED IT TO GROW EQUALLY IN ALL FOUR DIRECTIONS, now this would, almost always mean, that even for a simple expansion, the `vector` has to completely allocate to a whole new place +# Matrix as a Graph +---- + +The title mostly says it, i will complete it more as needed by the main project +This is a subproject for the worldline project (a catchy name, but an interesting small simulator for me) + +## Purpose - + +I needed a matrix like data structure, that can have +1. expansion and deletetion capabilities like that of a list (ie. no need to copy again and again for expansion as in std::vector (and i am not talking about the capacity vs size here, that would not work for my purpose)) + +2. access as a vector 2x2 matrix, or atleast fast access + +Then, i had read somewhere, _A matrix is inherently a graph, each node connected to 4 adjacent nodes_, though it maybe very simple, but quite intutive it seems. + +So, now the point of it, So i created a matrix data structure, based on a graph, that completes the requirements for `point 1 above`, though it doesn't have constant time lookups like std::vector, but for my case, i chose to create it like this. + +## Probable Uses - + +It will likely be used as the `world plot`, since think, this world will be expanding (continuosly or on need basis, so I didn't wanted `vector`, that had been quite an overhead for expansion like 40\*40 to 100\*100) +Also, in case of `vector`, you will likely have it grow in ONLY TWO DIRECTIONS, and I WANTED IT TO GROW EQUALLY IN ALL FOUR DIRECTIONS, now this would, almost always mean, that even for a simple expansion, the `vector` has to completely allocate to a whole new place diff --git a/graphMat/direction.hpp b/graphMat/direction.hpp index 19f9e5f..6af5125 100644 --- a/graphMat/direction.hpp +++ b/graphMat/direction.hpp @@ -1,12 +1,12 @@ -#pragma once - -#include - -enum Direction: uint8_t{ // intentionally not enum class now - UP, - DOWN, - RIGHT, - LEFT -}; - -typedef std::vector directionalPath; // can use std::queue too, that would allow popping too +#pragma once + +#include + +enum Direction: uint8_t{ // intentionally not enum class now + UP, + DOWN, + RIGHT, + LEFT +}; + +typedef std::vector directionalPath; // can use std::queue too, that would allow popping too diff --git a/graphMat/graph__square_mat.hpp b/graphMat/graph__square_mat.hpp index 3f59c93..408b833 100644 --- a/graphMat/graph__square_mat.hpp +++ b/graphMat/graph__square_mat.hpp @@ -1,2 +1,4 @@ #pragma once +#include "graph__square_mat_decl.hpp" +#include "graph_mat.hpp" diff --git a/graphMat/graph__square_mat_decl.hpp b/graphMat/graph__square_mat_decl.hpp index 7688e01..9b8dbce 100644 --- a/graphMat/graph__square_mat_decl.hpp +++ b/graphMat/graph__square_mat_decl.hpp @@ -10,8 +10,13 @@ class Square_Matrix: public Graph_Matrix{ dimen_t getOrder() const{ //order of the matrix return this->_total_y_abs; } - void resize(dimen_t new_order) override{ - this->resize(new_order, new_order); + void resize(dimen_t new_order){ + Graph_Matrix::resize(new_order, new_order); } + Square_Matrix(): Square_Matrix(1){} + Square_Matrix(dimen_t order): Graph_Matrix(order, order){ + + } + }; diff --git a/graphMat/graph_box.hpp b/graphMat/graph_box.hpp index d4c6936..39dba2f 100644 --- a/graphMat/graph_box.hpp +++ b/graphMat/graph_box.hpp @@ -5,7 +5,7 @@ #include #include "direction.hpp" -#include "includes/declarations.hpp" +#include "../includes/declarations.hpp" // equivalent to {x,y} in a matrix, this typedef defines the position of a box/point, in an intuitive way (to me atleast :D), and feels more closer to the implementation than to give indices, since here we have directions mostly typedef std::vector> graph_position; diff --git a/graphMat/graph_mat.hpp b/graphMat/graph_mat.hpp index 9ae2553..834e0d9 100644 --- a/graphMat/graph_mat.hpp +++ b/graphMat/graph_mat.hpp @@ -2,6 +2,12 @@ #include "graph_mat_decl.hpp" +#define DEBUG_MODE false /*turn on to get more logging*/ + +#if DEBUG_MODE +#include "test_util/node_conn.hpp" +#endif + //iterates over all the boxes template< typename node_type, typename dimen_t> bool Graph_Matrix::forRange(graph_box_type* iteratee){ //returns false when iterated all of that of that row @@ -15,7 +21,7 @@ bool Graph_Matrix::forRange(graph_box_type* iteratee){ //ret template< typename node_type, typename dimen_t> void Graph_Matrix::pushCol(){ // add a column at end - this->tr_box->right = new graph_box_type(0, this->_total_x_abs); + this->tr_box->right = new graph_box_type(this->_x_max+1, this->_y_max); this->tr_box->right->left = this->tr_box; graph_box_type* prev_new_box = this->tr_box->right; @@ -27,7 +33,7 @@ void Graph_Matrix::pushCol(){ // add a column at end dimen_t count{1}; while( last_col_iter != this->br_box ){ //ideally shouldn't be infinite, since last_col_iter->down should reach the bottom surely // we also have to give the previous box, left, right, down pointer to the new Box - last_col_iter->right = new graph_box_type(count, this->_total_x_abs); + last_col_iter->right = new graph_box_type(this->_x_max+1, this->_y_max - count); last_col_iter->right->left = last_col_iter; last_col_iter->right->up = prev_new_box; @@ -39,8 +45,9 @@ void Graph_Matrix::pushCol(){ // add a column at end } if( this->br_box != this->tr_box ){ - this->br_box->right = new graph_box_type(this->_total_y_abs-1, this->_total_x_abs); + this->br_box->right = new graph_box_type(this->_x_max+1, this->_y_min); prev_new_box->down = this->br_box->right; + prev_new_box->down->up = prev_new_box; this->br_box->right->left = this->br_box; this->br_box->right->up = prev_new_box; } @@ -48,12 +55,13 @@ void Graph_Matrix::pushCol(){ // add a column at end this->tr_box = this->tr_box->right; this->br_box = this->br_box->right; // new bottom right + ++(this->_x_max); ++(this->_total_x_abs); } template< typename node_type, typename dimen_t> -void Graph_Matrix::pushRow(){ // add a row at end - this->bl_box->down = new graph_box_type(this->_x_min-1, 0); +void Graph_Matrix::pushRow(){ // add a row at downward end + this->bl_box->down = new graph_box_type(this->_x_min, this->_y_min-1); this->bl_box->down->up = this->bl_box; graph_box_type* prev_new_box = this->bl_box->down; @@ -66,7 +74,7 @@ void Graph_Matrix::pushRow(){ // add a row at end // the below condition can be replaced with equivalent for loop using _N_Columns while( last_row_iter != this->br_box ){ //ideally shouldn't be infinite, since last_row_iter->right should reach the bottomRight surely // we also have to give the previous box, left, right, down pointer to the new Box - last_row_iter->down = new graph_box_type(this->_total_y_abs, count); + last_row_iter->down = new graph_box_type(this->_x_min + count, this->_y_min-1); last_row_iter->down->up = last_row_iter; last_row_iter->down->left = prev_new_box; @@ -78,8 +86,9 @@ void Graph_Matrix::pushRow(){ // add a row at end } if( this->br_box != this->bl_box ){ - this->br_box->down = new graph_box_type(this->_y_min - 1, this->-1); + this->br_box->down = new graph_box_type(this->_x_max, this->_y_min-1); prev_new_box->right = this->br_box->down; + prev_new_box->right->left = prev_new_box; this->br_box->down->up = this->br_box; this->br_box->down->left = prev_new_box; } @@ -87,83 +96,149 @@ void Graph_Matrix::pushRow(){ // add a row at end this->bl_box = this->bl_box->down; this->br_box = this->br_box->down; // new bottom right - --(_y_min); // ie. increase in negative + --(this->_y_min); // ie. increase in negative ++(this->_total_y_abs); } template< typename node_type, typename dimen_t> -void Graph_Matrix::injectCol(){ // add a column at begin - this->origin.left = new graph_box_type(0,0); - this->origin.left->right = &(this->origin); +void Graph_Matrix::injectCol(){ // add a column at leftmost + this->tl_box->left = new graph_box_type(this->_x_min-1, this->_y_max); + this->tl_box->left->right = this->tl_box; - graph_box_type* prev_new_box = this->origin.right; + graph_box_type* prev_new_box = this->tl_box->left; //the latest new box // @future- Can use util::range_iterator later, for the same iteration - graph_box_type* last_col_iter = this->origin.down != nullptr ? this->origin.down : this->bl_box; //iterator in last column + graph_box_type* last_col_iter = this->tl_box->down != nullptr ? this->tl_box->down : this->bl_box; //iterator in last column // in the else case of ?: so that the next loop doesn't execute in case the matrix contained only 1 row + dimen_t count{1}; + #if DEBUG_MODE + test::logger::__IsConncted(this->tl_box, this->bl_box, DOWN); + test::logger::__IsConncted(last_col_iter, this->bl_box, DOWN); + #endif + // @CAUTION - Seg Fault here, Cause-> tl_box and bl_box aren't connected in a up to down fashion while( last_col_iter != this->bl_box ){ //ideally shouldn't be infinite, since last_col_iter->down should reach the bottom surely // we also have to give the previous box, left, right, down pointer to the new Box - last_col_iter->left = new graph_box_type; + last_col_iter->left = new graph_box_type(this->_x_min-1, this->_y_max - count); last_col_iter->left->right = last_col_iter; last_col_iter->left->up = prev_new_box; prev_new_box->down = last_col_iter->left; prev_new_box = last_col_iter->left; last_col_iter = last_col_iter->down; + + ++count; } - if( this->bl_box != &(this->origin) ){ - this->bl_box->left = new graph_box_type; + #if DEBUG_MODE + test::logger::__IsConncted(this->tl_box, this->bl_box, DOWN); + #endif + if( this->bl_box != this->tl_box ){ + this->bl_box->left = new graph_box_type(this->_x_min-1, this->_y_min ); prev_new_box->down = this->bl_box->left; + prev_new_box->down->up = prev_new_box; this->bl_box->left->right = this->bl_box; this->bl_box->left->up = prev_new_box; } - this->origin = &(this->origin.left); - this->br_box = this->br_box->left; // new bottom right + this->tl_box = this->tl_box->left; + this->bl_box = this->bl_box->left; // new bottom right + --(this->_x_min); //increment in negative side ++(this->_total_x_abs); } template< typename node_type, typename dimen_t> void Graph_Matrix::injectRow(){ // add a row at begin - this->origin.up = new graph_box_type; - this->origin.up->down = &(this->origin); + this->tl_box->up = new graph_box_type(this->_x_min, this->_y_max+1); + this->tl_box->up->down = this->tl_box; - graph_box_type* prev_new_box = this->origin.up; + graph_box_type* prev_new_box = this->tl_box->up; //the latest new box - graph_box_type* last_row_iter = this->origin.right != nullptr ? this->origin.right : this->tr_box; //iterator in last column + graph_box_type* last_row_iter = this->tl_box->right != nullptr ? this->tl_box->right : this->tr_box; //iterator in last column // in the else case of ?: so that the next loop doesn't execute in case the matrix contained only 1 row + dimen_t count{1}; // the below condition can be replaced with equivalent for loop using _N_Columns while( last_row_iter != this->tr_box ){ //ideally shouldn't be infinite, since last_row_iter->right should reach the bottomRight surely // we also have to give the previous box, left, right, down pointer to the new Box - last_row_iter->up = new graph_box_type; + last_row_iter->up = new graph_box_type(this->_x_min+count, this->_y_max+1); last_row_iter->up->down = last_row_iter; last_row_iter->up->left = prev_new_box; prev_new_box->right = last_row_iter->up; prev_new_box = last_row_iter->up; last_row_iter = last_row_iter->right; + + ++count; } - if( this->tr_box != &(this->origin) ){ - this->tr_box->up = new graph_box_type; + if( this->tr_box != this->tl_box ){ // ie. row was not having only one element, since in that case we already did a new graph_box_type + this->tr_box->up = new graph_box_type(this->_x_max, this->_y_max + 1); prev_new_box->right = this->tr_box->up; + prev_new_box->right->left = prev_new_box; this->tr_box->up->down = this->tr_box; this->tr_box->left->up = prev_new_box; } - this->origin = *(this->origin.up); + this->tl_box = this->tl_box->up; this->tr_box = this->tr_box->up; // new top right + ++(this->_y_max); ++(this->_total_y_abs); } template< typename node_type, typename dimen_t> -void Graph_Matrix::popCol(){ //remove the last column ( = n_col-1) - if( this->tr_box == &(this->origin) ) return; //don't pop out the origin +void Graph_Matrix::popRow_upper(){ //remove the uppermost row ( = y_max) + if( this->tl_box == this->bl_box ) return; //don't pop out the origin row (y=0) + + graph_box_type* temp = this->tl_box; + this->tl_box = this->tl_box->down; //since this bl_box will be removed + + // we have to clear the right pointers of this->bl_box here + while( temp != this->tr_box ){ + temp->down->up = nullptr; // logically temp->left != nullptr, since atleast it will point to an element in the origin 1st column + temp = temp->right; + + delete temp->left; + } + + this->tr_box = this->tr_box->down; + delete this->tr_box->up; + this->tr_box->up = nullptr; + + --(this->_y_max); + --(this->_total_y_abs); +} + +template< typename node_type, typename dimen_t> +void Graph_Matrix::popCol_left(){ //remove the leftmost column; INTERNAL but can be used + if( this->tl_box == this->tr_box ) return; //don't pop out the origin column (x=0) + + graph_box_type* temp = this->tl_box; + this->tl_box = this->tl_box->right; + + // we have to clear the down pointers of this->tr_box here + while( temp != this->bl_box ){ + temp->right->left = nullptr; + temp = temp->down; + + delete temp->up; + }; + + this->bl_box = this->bl_box->right; + delete this->bl_box->left; + this->bl_box->left = nullptr; + + ++(this->_x_min); //decrement in negative + --(this->_total_x_abs); +} + +template< typename node_type, typename dimen_t> +void Graph_Matrix::popCol(){ //by default, removes the rightmost column ( = x_max ), if not available calls popCol_front() to try to remove the leftmost column, so it's safe to just use this function only + if( this->tr_box == this->tl_box ) return; //don't pop out the origin column (x=0) + + if( this->_x_max == 0 ) return this->popCol_left(); graph_box_type* temp = this->tr_box; this->tr_box = this->tr_box->left; @@ -180,12 +255,15 @@ void Graph_Matrix::popCol(){ //remove the last column ( = delete this->br_box->right; this->br_box->right = nullptr; + --(this->_x_max); --(this->_total_x_abs); } template< typename node_type, typename dimen_t> void Graph_Matrix::popRow(){ //remove the last row ( = n_row-1) - if( this->bl_box == &(this->origin) ) return; //don't pop out the origin + if( this->tl_box == this->bl_box ) return; //don't pop out the origin row (y=0) + + if( this->_y_min == 0 ) return this->popRow_upper(); graph_box_type* temp = this->bl_box; this->bl_box = this->bl_box->up; //since this bl_box will be removed @@ -203,11 +281,12 @@ void Graph_Matrix::popRow(){ //remove the last row ( = n_r delete this->br_box->down; this->br_box->down = nullptr; + ++(this->_y_min); //decrement in negative side --(this->_total_y_abs); } template< typename node_type, typename dimen_t> -std::pair< dimen_t, dimen_t > Graph_Matrix::getDimensions() const{ +std::pair< std::make_unsigned_t, std::make_unsigned_t > Graph_Matrix::getDimensions() const{ return { this->_total_y_abs, this->_total_x_abs }; //return in form of rows, cols } @@ -226,13 +305,13 @@ void Graph_Matrix::displayMat(std::ostream& os) const{ // @todo - Use util::range_iterator here to iterate through all boxes // temporary code - const graph_box_type* box = &(this->origin); - const graph_box_type* row_start = &(this->origin); + const graph_box_type* box = this->tl_box; + const graph_box_type* row_start = this->tl_box; while( row_start != nullptr ){ box = row_start; while( box != nullptr ){ - os << box->data << " | "; + os << box->coords << " | "; box = box->right; } os << '\n'; @@ -241,40 +320,108 @@ void Graph_Matrix::displayMat(std::ostream& os) const{ } template< typename node_type, typename dimen_t> -void Graph_Matrix::resize(udimen_t x_dimen, udimen_t y_dimen){ +void Graph_Matrix::resize(dimen_t _num_rows, dimen_t _num_cols){ // @future - Use this->__capacity to, use the nodes, previously allocated only, instead of allocating again + if( _num_rows < 0 || _num_cols < 0 ){ + throw std::length_error("Cannot have a graph with negative dimensions"); + } - if( x_dimen == 0 || y_dimen == 0 ) return; //as for now, don't allow 0 cols or rows, though even later it is less probable to have such behaviour + if( _num_cols == 0 || _num_rows == 0 ) return; //as for now, don't allow 0 cols or rows, though even later it is less probable to have such behaviour + + --_num_cols; --_num_rows; //to adapt to the usual coordinate system, so that if user asks to resize to 1x1, program understands as 0x0 which is the origin // @future - Instead of simply popping, prefer to change size only, utilizing __capacity - while( y_dimen < this->_total_x_abs ){ - this->popCol(); - } - while( x_dimen < this->_total_y_abs ){ + while( _num_rows < this->_total_y_abs ){ this->popRow(); } - x_dimen -= this->_total_y_abs; //x_dimen and y_dimen will now how how many `more` to add - y_dimen -= this->_total_x_abs; +#if DEBUG_MODE + test::logger::__IsConncted(tl_box, bl_box, DOWN); + test::logger::__IsConncted(tl_box, tr_box, RIGHT); + test::logger::__IsConncted(tr_box, br_box, DOWN); + test::logger::__IsConncted(bl_box, br_box, RIGHT); +#endif - dimen_t left_inc, right_inc, down_inc, up_inc; - up_inc = y_dimen / 2; - down_inc = y_dimen - y_dimen / 2; - left_inc = x_dimen / 2; - right_inc = x_dimen - x_dimen / 2; + while( _num_cols < this->_total_x_abs ){ + this->popCol(); + } + +#if DEBUG_MODE + test::logger::__IsConncted(tl_box, bl_box, DOWN); + test::logger::__IsConncted(tl_box, tr_box, RIGHT); + test::logger::__IsConncted(tr_box, br_box, DOWN); + test::logger::__IsConncted(bl_box, br_box, RIGHT); +#endif - while( down_inc-- > 0 ){ //add x_dimen/2 columns, to bottom + _num_cols -= this->_total_x_abs; //_num_cols and _num_rows will now how how many `more` to add + _num_rows -= this->_total_y_abs; + + dimen_t left_inc, right_inc, down_inc, up_inc; + up_inc = _num_rows / 2; + down_inc = _num_rows - _num_rows / 2; + left_inc = _num_cols / 2; + right_inc = _num_cols - _num_cols / 2; + +#if DEBUG_MODE + this->displayMat(); + std::cout << std::endl; +#endif + while( down_inc-- > 0 ){ //add _num_cols/2 columns, to bottom this->pushRow(); } - while( up_inc-- > 0 ){ //add x_dimen-x_dimen/2 cols, above +#if DEBUG_MODE + test::logger::__IsConncted(tl_box, bl_box, DOWN); + test::logger::__IsConncted(tl_box, tr_box, RIGHT); + test::logger::__IsConncted(tr_box, br_box, DOWN); + test::logger::__IsConncted(bl_box, br_box, RIGHT); +#endif + +#if DEBUG_MODE + this->displayMat(); + std::cout << std::endl; +#endif + while( up_inc-- > 0 ){ //add _num_cols-_num_cols/2 cols, above this->injectRow(); } - while( right_inc-- > 0 ){ //add y_dimen/2 cols, to right +#if DEBUG_MODE + test::logger::__IsConncted(tl_box, bl_box, DOWN); + test::logger::__IsConncted(tl_box, tr_box, RIGHT); + test::logger::__IsConncted(tr_box, br_box, DOWN); + test::logger::__IsConncted(bl_box, br_box, RIGHT); +#endif + +#if DEBUG_MODE + this->displayMat(); + std::cout << std::endl; +#endif + while( right_inc-- > 0 ){ //add _num_rows/2 cols, to right this->pushCol(); } - while( left_inc-- > 0 ){ //add y_dimen-y_dimen/2 cols, to left + +#if DEBUG_MODE + test::logger::__IsConncted(tl_box, bl_box, DOWN); + test::logger::__IsConncted(tl_box, tr_box, RIGHT); + test::logger::__IsConncted(tr_box, br_box, DOWN); + test::logger::__IsConncted(bl_box, br_box, RIGHT); +#endif +#if DEBUG_MODE + this->displayMat(); + std::cout << std::endl; +#endif + while( left_inc-- > 0 ){ //add _num_rows-_num_rows/2 cols, to left this->injectCol(); } +#if DEBUG_MODE + this->displayMat(); + std::cout << std::endl; +#endif + +#if DEBUG_MODE + test::logger::__IsConncted(tl_box, bl_box, DOWN); + test::logger::__IsConncted(tl_box, tr_box, RIGHT); + test::logger::__IsConncted(tr_box, br_box, DOWN); + test::logger::__IsConncted(bl_box, br_box, RIGHT); +#endif } @@ -322,7 +469,11 @@ Graph_Matrix::Graph_Matrix() : Graph_Matrix(1, 1){} template< typename node_type, typename dimen_t> // @look_later - Here, for now i have initialised _x_min and _x_max as given below, but shouldn't they both be 0,0 ? Same for _y_min and _y_max ? -Graph_Matrix::Graph_Matrix(dimen_t _x_dimen, dimen_t _y_dimen) : _total_x_abs(1), _total_y_abs(1), _x_min(0), _x_max(1), _y_min(0), _y_max(1), origin(0,0){ +Graph_Matrix::Graph_Matrix(dimen_t _num_rows, dimen_t _num_cols) : _total_x_abs(0), _total_y_abs(0), _x_min(0), _x_max(0), _y_min(0), _y_max(0), origin(0,0){ + if( _num_rows < 0 || _num_cols < 0 ){ + throw std::length_error("Cannot have a graph with negative dimensions"); + } + this->origin.data = decltype(this->origin.data){}; // @caution -> due to this , and maybe code at other places, the `node_type` has to copy-constructible this->tl_box = &origin; @@ -330,26 +481,36 @@ Graph_Matrix::Graph_Matrix(dimen_t _x_dimen, dimen_t _y_dime this->tr_box = &origin; this->br_box = &origin; - while( --(_x_dimen) ){ //add _x_dimen-1 columns (already initialises by one default) + while( --(_num_rows) ){ //add _num_rows-1 columns (already initialises by one default) this->pushRow(); } - while( --(_y_dimen) ){ //add _y_dimen-1 columns (already initialises by one default) + while( --(_num_cols) ){ //add _num_cols-1 columns (already initialises by one default) this->pushCol(); } + +#if DEBUG_MODE + test::logger::__IsConncted(tl_box, bl_box, DOWN); + test::logger::__IsConncted(tl_box, tr_box, RIGHT); + test::logger::__IsConncted(tr_box, br_box, DOWN); + test::logger::__IsConncted(bl_box, br_box, RIGHT); +#endif + } template< typename node_type, typename dimen_t> Graph_Matrix::~Graph_Matrix(){ - // @todo : May cause problem, when only single element exists... if tried to delete the three pointers from the bottom - - using std::cout; using std::endl; - while( this->_total_y_abs != 1 ){ //excluding the origin node, which will automatically get destructed, since it's not a pointer + while( this->_total_y_abs != 0 ){ //excluding the origin node, which will automatically get destructed, since it's not a pointer popRow(); //remove the last row ( = n_row-1) } - while( this->_total_x_abs != 1 ){ //excluding the origin node, which will automatically get destructed, since it's not a pointer + while( this->_total_x_abs != 0 ){ //excluding the origin node, which will automatically get destructed, since it's not a pointer popCol(); } + +#if DEBUG_MODE + using std::cout; using std::endl; + clog << "Removed all"<< endl; +#endif } // CONSTRUCTORS AND DESTRUCTORS // diff --git a/graphMat/graph_mat_decl.hpp b/graphMat/graph_mat_decl.hpp index 51429b4..a768ae3 100644 --- a/graphMat/graph_mat_decl.hpp +++ b/graphMat/graph_mat_decl.hpp @@ -2,8 +2,14 @@ /* @NOTE- * This class is originally meant to be inherited to from, to provide implementations as needed per your needs - * THOUGH, IF YOU ALLOCATE MEMORY IN IT, BE SURE TO TAKE CARE OF THAT AT DESTRUCTION, I CURRENTLY DONT KNOW MUCH OF VIRTUAL DESTRUCTORS, WILL MODIFY AS NEEDED - * I appreciate help regarding it (you may find this vague for me trying all this wuthout much knowledge of virtual destructors, i have read of them, but never used) + * + * @NOTE - Regarding how the graph is stored (maybe slighlty confusing at beginning) -> + * Internally all nodes are stored and given coordinate values as per the usual x-y coordinate system + * + * But, for the user side, the main functions exposed are -> the constructor taking arguments in form of row*col + * and, the resize function taking arguments in form of row*col + * The thing to understand here is, that the user is entering according to the usual matrix size (row*column form), + * but the coordinates won't be like that, for example, going down, the x_coord as in matrix won't increase, the y will increase, same for y coordinates */ #include @@ -15,10 +21,11 @@ // @limitation (wrt vector) - Currently you can't get back the nth row, say mat[4], isn't valid, though can be implemented by simply returning, mat[4][0] which will logically be a linked list // dimen_t will be the unit of dimension -template< typename node_type, typename dimen_t=int32_t> +template< typename node_type, typename dimen_t=int32_t> // @concepts -> make sure that std::is_signed == true class Graph_Matrix{ + static_assert(std::is_signed_v == true); typedef Graph_Box graph_box_type; - typedef std::make_unsigned udimen_t; + typedef std::make_unsigned_t udimen_t; // typedef int32_t dimen_t; //dimension unit protected: @@ -44,9 +51,14 @@ class Graph_Matrix{ dimen_t _y_min, _y_max; // @warning - May later change it as well to `dimen_t`, since `if _total_y_abs and _N_cols are used in substraction, it may well cause `wrapping around of the unsigned`` + + // these ..._abs are basically ..._max - ..._min udimen_t _total_y_abs; // originally it was named `_N_Rows`, but the name has been changed to adopt to the usual x-y coordinate system, AND for each box to have coordinates, which required updation of all coordinates, like if a row is added, origin(0,0) shifted downwards, so all other coords should change as well udimen_t _total_x_abs; // originally names `_N_Cols` + void popCol_left(); // remove the leftmost column + void popRow_upper(); // remove the upmost row + public: // @deprecated+incomplete -> use util::range_iterator for now // @note - util::range_iterator has ben postponed for now, will be implemented as needed @@ -57,10 +69,10 @@ class Graph_Matrix{ void injectCol(); // add a column at begin void injectRow(); // add a row at begin - void popCol(); // add a column at end - void popRow(); // add a row at end + void popCol(); // removes a column, preferably rightmost, if not calls popCol_left() + void popRow(); // removes a row, preferably downmost, if not calls popRow_upper() - virtual std::pair< dimen_t, dimen_t > getDimensions() const; // returns in form of + virtual std::pair< udimen_t, udimen_t > getDimensions() const; // returns in form of auto getNumRows() const; auto getNumCols() const; @@ -76,7 +88,7 @@ class Graph_Matrix{ // void shrink_to_fit(); // virtual void resize(dimen_t x_dimen, dimen_t y_dimen, Direction a, ...); // @future - resize with variadic arguments, that takes directions after the new dimensions - virtual void resize(udimen_t x_dimen, udimen_t y_dimen); + virtual void resize(dimen_t _num_rows, dimen_t _num_cols); void displayMat(std::ostream& output_stream = std::cout) const; @@ -85,7 +97,7 @@ class Graph_Matrix{ // } Graph_Matrix(); - Graph_Matrix(dimen_t _x_dimen, dimen_t _y_dimen); + Graph_Matrix(dimen_t _num_rows, dimen_t _num_cols); // Graph_Matrix(dimen_t _x_dimen, dimen_t _y_dimen, std::function); //takes a function, that takes in two values (the x and y coord of that point), and give out a value to be alloted to the new box created there ~Graph_Matrix(); }; diff --git a/graphMat/graph_path_finder.hpp b/graphMat/graph_path_finder.hpp index af2e6ea..ffd0a0f 100644 --- a/graphMat/graph_path_finder.hpp +++ b/graphMat/graph_path_finder.hpp @@ -1,27 +1,27 @@ -#pragma once - -#include "includes/snake.hpp" -#include "includes/declarations.hpp" -#include "includes/forward_decl.hpp" - -#include - -typedef std::vector<_coord> Path; - -class PathFinder{ - /* - The PathFinder functions will need 3 things -> - 1. Start Pos (will be head of snake) - 2. End Pos (will be parent_world->food) - 3, Obstacles to consider (which is major reason for needing world) - - Though we don't need to take in the world reference here, since it's already binded with the snake - */ - - typedef std::shared_ptr World_Ptr; - public: - static Path getPath( const Snake*, _coord); - - static bool pathIsClear( const World_Ptr, const Path&); - -}; +#pragma once + +#include "includes/snake.hpp" +#include "includes/declarations.hpp" +#include "includes/forward_decl.hpp" + +#include + +typedef std::vector<_coord> Path; + +class PathFinder{ + /* + The PathFinder functions will need 3 things -> + 1. Start Pos (will be head of snake) + 2. End Pos (will be parent_world->food) + 3, Obstacles to consider (which is major reason for needing world) + + Though we don't need to take in the world reference here, since it's already binded with the snake + */ + + typedef std::shared_ptr World_Ptr; + public: + static Path getPath( const Snake*, _coord); + + static bool pathIsClear( const World_Ptr, const Path&); + +}; diff --git a/graphMat/test.cxx b/graphMat/test.cxx index 2e8a693..f57cfb3 100644 --- a/graphMat/test.cxx +++ b/graphMat/test.cxx @@ -1,16 +1,33 @@ #include -#include "graph_mat.hpp" +#include "graph__square_mat.hpp" using namespace std; +// LEARNT - make_unsigned_t<> is just make_unsigned<>::type... that was why it doesn't define any operators, make_unsigned is always a struct, while make_unsigned_t is not +typedef std::make_unsigned::type udimen; + int main(int argc, char const *argv[]) { - Graph_Matrix mat(6,6); - // Graph_Matrix mat; + udimen a = 34; + if( a == -2 ){ + cout<<"Error"< mat(init_order); + // mat.displayMat(); + // mat.resize(final_order); + // mat.displayMat(); + + int init_rows{4}, init_cols{8}, final_rows{3}, final_cols{15}; + Graph_Matrix mat(init_rows,init_cols); + mat.displayMat(); + mat.resize(final_rows, final_cols); + mat.displayMat(); - mat.displayMat(); return 0; } diff --git a/graphMat/test_util/node_conn.hpp b/graphMat/test_util/node_conn.hpp new file mode 100644 index 0000000..157c56e --- /dev/null +++ b/graphMat/test_util/node_conn.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "graph_box.hpp" +#include + +using std::clog, std::endl; + + // for logging mainly (not literally 'tests' though) +namespace test{ + namespace logger{ + template + bool __IsConncted( const Graph_Box* from, const Graph_Box* to , Direction dir ){ + const Graph_Box* temp{ from }; + + bool boolean{false}, b2{false}; + for (int i = 0; temp!=nullptr && i < 100; i++){ + if( temp == to ){ + clog<<"Connected"<get_adj_box(dir); + } + + dir = test::__invertDirection(dir); + temp = to; + + for (int i = 0; temp!=nullptr && i < 100; i++){ + if( temp == from ){ + clog<<"Connected Reversed too"<get_adj_box(dir); + } + + if(!boolean || !b2) clog<<"Not Connected"< +template // @assert - dimen_t must be integral type struct _coord{ dimen_t mX, mY; + friend std::ostream& operator<<(std::ostream& os, const _coord& coord){ + if(coord.mX >= 0){ + os << ' '; + if(coord.mX < 10) + os << ' '; + }else if(coord.mX > -10) + os << ' '; + os << coord.mX <<','; + if(coord.mY >= 0){ + os << ' '; + if(coord.mY < 10) + os << ' '; + }else if(coord.mY > -10) + os << ' '; + + os << coord.mY; + return os; + } + _coord(dimen_t x, dimen_t y): mX(x), mY(y){} }; diff --git a/includes/world_plot.hpp b/includes/world_plot.hpp index f390b31..cc8fa0e 100644 --- a/includes/world_plot.hpp +++ b/includes/world_plot.hpp @@ -1,14 +1,14 @@ -#pragma once - -#include "graphMat/graph__square_mat_decl.hpp" -#include "includes/declarations.hpp" - -class WorldPlot: public Square_Matrix<_box>{ - public: - bool isPathClear( const Graph_Box<_box>* origin, const directionalPath& path ) const; - - WorldPlot(); - WorldPlot(const WorldPlot&) = delete; - WorldPlot(const WorldPlot&&) = delete; - -}; +#pragma once + +#include "graphMat/graph__square_mat_decl.hpp" +#include "includes/declarations.hpp" + +class WorldPlot: public Square_Matrix<_box>{ + public: + bool isPathClear( const Graph_Box<_box>* origin, const directionalPath& path ) const; + + WorldPlot(); + WorldPlot(const WorldPlot&) = delete; + WorldPlot(const WorldPlot&&) = delete; + +}; diff --git a/src/world_plot.cpp b/src/world_plot.cpp index fc9ae09..841cab3 100644 --- a/src/world_plot.cpp +++ b/src/world_plot.cpp @@ -1,16 +1,16 @@ -#include "world_plot.hpp" - -bool WorldPlot::isPathClear( const Graph_Box<_box>* origin, const directionalPath& path ) const{ - const Graph_Box<_box> *temp{ origin }; - - for ( uint32_t i = 0; iget_adj_box(path[i]); - if( ! temp->getData().entities.empty() ) return false; - } - - return true; -} - -WorldPlot::WorldPlot(){ - -} +#include "world_plot.hpp" + +bool WorldPlot::isPathClear( const Graph_Box<_box>* origin, const directionalPath& path ) const{ + const Graph_Box<_box> *temp{ origin }; + + for ( uint32_t i = 0; iget_adj_box(path[i]); + if( ! temp->getData().entities.empty() ) return false; + } + + return true; +} + +WorldPlot::WorldPlot(){ + +}