Skip to content

Instantly share code, notes, and snippets.

@stfuchs
Last active October 6, 2017 09:06
Show Gist options
  • Save stfuchs/91c7e5f67e5d112b2adcc9ca855b52ad to your computer and use it in GitHub Desktop.
Save stfuchs/91c7e5f67e5d112b2adcc9ca855b52ad to your computer and use it in GitHub Desktop.
Rotate image matrix clockwise inplace
#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