Last active
October 6, 2017 09:06
-
-
Save stfuchs/91c7e5f67e5d112b2adcc9ca855b52ad to your computer and use it in GitHub Desktop.
Rotate image matrix clockwise inplace
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <vector> | |
/* | |
* Rotate square matrix by 90 deg clock wise. | |
*/ | |
template<typename T> | |
bool rotateMatrix(std::vector< std::vector<T> >& mat) | |
{ | |
int n = mat.size(); | |
// check matrix size | |
if (n==0) { return false; } | |
for (const auto& row: mat) | |
{ | |
if (static_cast<int>(row.size()) != n) { return false; } | |
} | |
for (int layer=0; layer<int(n/2); ++layer) | |
{ | |
int first = layer; | |
int last = n - 1 - layer; | |
for (int i=first; i<last; ++i) | |
{ | |
T tmp = mat[layer][i]; | |
mat[layer][i] = mat[n-1-i][layer]; | |
mat[n-1-i][layer] = mat[n-1-layer][n-1-i]; | |
mat[n-1-layer][n-1-i] = mat[i][n-1-layer]; | |
mat[i][n-1-layer] = tmp; | |
} | |
} | |
return true; | |
} | |
/* | |
* Print matrix to stdout one row per line. | |
*/ | |
template<typename T> | |
void printMatrix(const T& vec) | |
{ | |
for (const auto& row: vec) | |
{ | |
for (const auto& col: row){ std::cout << " " << col; } | |
std::cout << std::endl; | |
} | |
} | |
/* | |
* A policy class to convert string to something else. | |
*/ | |
template<typename T> | |
struct StringConversion | |
{ | |
inline static T fromString(const std::string& in) { return T(in); } | |
}; | |
/* | |
* A specialization to convert string to int. | |
*/ | |
template<> | |
inline int StringConversion<int>::fromString(const std::string& in) | |
{ | |
return std::stoi(in); | |
} | |
/* | |
* Another policy class to convert a hex string to int. | |
*/ | |
struct HexStringToInt | |
{ | |
inline static int fromString(const std::string& in) | |
{ | |
return std::stoi(in, 0, 16); | |
} | |
}; | |
/* | |
* Split a string by delimiter. | |
* This helper optionally converts each element based | |
* on the selected policy. | |
*/ | |
template<typename T=std::string, typename Policy=StringConversion<T> > | |
std::vector<T> split(const std::string& value, char delim) | |
{ | |
std::vector<T> res; | |
std::string::size_type start = 0; | |
std::string::size_type match; | |
while ( (match = value.find(delim, start)) != std::string::npos ) | |
{ | |
res.push_back(Policy::fromString(value.substr(start, match-start))); | |
start = match + 1; | |
} | |
res.push_back(Policy::fromString(value.substr(start))); | |
return res; | |
} | |
int main(int argc, char** argv) | |
{ | |
if (argc != 2) | |
{ | |
std::cout << "Usage: rotate_matrix matrix.txt" << std::endl; | |
std::cout << std::endl; | |
std::cout << "Expected file format:" << std::endl; | |
std::cout << "0 1 2" << std::endl; | |
std::cout << "3 4 5" << std::endl; | |
std::cout << "6 7 8" << std::endl; | |
return EXIT_FAILURE; | |
} | |
std::string filename = argv[1]; | |
char delim = ' '; | |
std::ifstream fin(filename); | |
if (!fin.is_open()) | |
{ | |
std::cout << "failed to open " << filename << std::endl; | |
return EXIT_FAILURE; | |
} | |
std::vector<std::vector<std::string> > mat; | |
for (std::string line; std::getline(fin, line); ) | |
{ | |
//mat.push_back(split<int, HexStringToInt>(line, delim)); | |
mat.push_back(split<>(line, delim)); | |
} | |
printMatrix(mat); | |
std::cout << std::endl; | |
if (rotateMatrix(mat)) | |
{ | |
printMatrix(mat); | |
} | |
else | |
{ | |
std::cout << "Not a square matrix" << std::endl; | |
return EXIT_FAILURE; | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment