Last active
August 29, 2015 14:07
-
-
Save adrian17/be20590be73ae30a5d1d to your computer and use it in GitHub Desktop.
EdgeSolver with templates
This file contains 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 <vector> | |
#include <string> | |
#include <array> | |
#include <fstream> | |
using std::cout; | |
using std::endl; | |
typedef std::vector<std::array<char, 4>> Board; | |
void fastswap(Board::iterator it1, Board::iterator it2){ | |
std::swap(*(int*)it1->data(), *(int*)it2->data()); | |
} | |
void fastrot(Board::iterator it) { | |
static_assert(sizeof(int) == 4, "rotation will not work"); | |
int &val = *(int*)it->data(); | |
val = (val << 8) | (val >> ((sizeof(int) * 8 - 8))); | |
} | |
template<int size> | |
bool checkLeftEdge(Board::iterator begin, Board::iterator right){ | |
if ((right - begin) % size == 0) | |
return true; | |
auto left = right - 1; | |
char c1 = (*right)[3], c2 = (*left)[1]; | |
return c1 - 32 == c2 || c1 == c2 - 32; | |
} | |
template<int size> | |
bool checkTopEdge(Board::iterator begin, Board::iterator bottom){ | |
if (bottom < begin + size) | |
return true; | |
auto top = bottom - size; | |
char c1 = (*bottom)[0], c2 = (*top)[2]; | |
return c1 - 32 == c2 || c1 == c2 - 32; | |
} | |
template<int size> | |
inline bool isLastElementValid(Board::iterator begin, Board::iterator last){ | |
return | |
checkTopEdge<size>(begin, last) && | |
checkLeftEdge<size>(begin, last); | |
} | |
template<int size> | |
bool recurse(Board::iterator begin, Board::iterator end, Board::iterator len){ | |
if (len == end) | |
return true; | |
for (auto it = len; it != end; ++it){ | |
fastswap(len, it); | |
for (int j = 0; j < 4; ++j){ | |
if (isLastElementValid<size>(begin, len)){ | |
bool success = recurse<size>(begin, end, len + 1); | |
if (success) | |
return true; | |
} | |
fastrot(len); | |
} | |
fastswap(len, it); | |
} | |
return false; | |
} | |
int to_index(int x, int y, int size){ return y * size + x; } | |
void draw(const Board &board, int size){ | |
for (int y = 0; y < size; ++y){ | |
cout << std::string(size * 4 + 1, '-') << endl; | |
for (int x = 0; x < size; ++x) | |
cout << "| " << board[to_index(x, y, size)][0] << " "; | |
cout << "|" << endl; | |
for (int x = 0; x < size; ++x) | |
cout << "|" << board[to_index(x, y, size)][3] << " " << board[to_index(x, y, size)][1]; | |
cout << "|" << endl; | |
for (int x = 0; x < size; ++x) | |
cout << "| " << board[to_index(x, y, size)][2] << " "; | |
cout << "|" << endl; | |
} | |
cout << std::string(size * 4 + 1, '-') << endl; | |
cout << endl; | |
} | |
int main(){ | |
std::ifstream in ("in.txt"); | |
if (!in) | |
return 1; | |
int size; | |
in >> size; | |
Board board(size * size); | |
for (auto& str : board){ | |
in.ignore(); | |
in.read(str.data(), 4); | |
} | |
bool success = false; | |
if(size == 2) success = recurse<2>(board.begin(), board.end(), board.begin()); | |
else if(size == 3) success = recurse<3>(board.begin(), board.end(), board.begin()); | |
else if(size == 4) success = recurse<4>(board.begin(), board.end(), board.begin()); | |
else if(size == 5) success = recurse<5>(board.begin(), board.end(), board.begin()); | |
if (success) | |
draw(board, size); | |
std::cin.ignore(); | |
std::cin.get(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment