Created
December 29, 2014 15:09
-
-
Save itarato/04c9d2850513ff43eb87 to your computer and use it in GitHub Desktop.
Sudoku maps - all, sorted
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 <vector> | |
#include <cmath> | |
#define SUDOKU_SIZE 9 | |
#define COORD_2_IDX(a, b) (SUDOKU_SIZE * a + b) | |
#define IDX_2_COORD_I(a) (floor(a / SUDOKU_SIZE)) | |
#define IDX_2_COORD_J(a) (a % SUDOKU_SIZE) | |
using namespace std; | |
typedef int value_type; | |
typedef vector<value_type> map_type; | |
class SudokuMap { | |
public: | |
SudokuMap () : map{map_type(pow(SUDOKU_SIZE, 2))} { }; | |
value_type getIJ(int i, int j); | |
value_type getIJ(int idx); | |
void setIJ(int i, int j, value_type value); | |
void setIJ(int idx, value_type value); | |
void solve(); | |
friend ostream& operator<<(ostream& os, const SudokuMap& s); | |
private: | |
map_type map; | |
bool isValid(); | |
}; | |
value_type SudokuMap::getIJ(int i, int j) { | |
return map[COORD_2_IDX(i, j)]; | |
} | |
value_type SudokuMap::getIJ(int idx) { | |
return map[idx]; | |
} | |
void SudokuMap::setIJ(int i, int j, value_type value) { | |
map[COORD_2_IDX(i, j)] = value; | |
} | |
void SudokuMap::setIJ(int idx, value_type value) { | |
map[idx] = value; | |
} | |
bool SudokuMap::isValid() { | |
int blockPosMap[] = { | |
0, 3, 6, | |
27, 30, 33, | |
54, 57, 60 | |
}; | |
int blockInnerMap[] = { | |
0, 1, 2, | |
9, 10, 11, | |
18, 19, 20 | |
}; | |
for (int i = 0; i < SUDOKU_SIZE; i++) { | |
bool colFlag[SUDOKU_SIZE + 1] = {}; | |
bool rowFlag[SUDOKU_SIZE + 1] = {}; | |
bool blockFlag[SUDOKU_SIZE + 1] = {}; | |
for (int j = 0; j < SUDOKU_SIZE; j++) { | |
value_type colVal = getIJ(j, i); | |
if (colVal > 0 && colFlag[colVal]) { | |
return false; | |
} | |
colFlag[colVal] = true; | |
value_type rowVal = getIJ(i, j); | |
if (rowVal > 0 && rowFlag[rowVal]) { | |
return false; | |
} | |
rowFlag[rowVal] = true; | |
value_type blockVal = getIJ(blockPosMap[i] + blockInnerMap[j]); | |
if (blockVal > 0 && blockFlag[blockVal]) { | |
return false; | |
} | |
blockFlag[blockVal] = true; | |
} | |
} | |
return true; | |
} | |
void SudokuMap::solve() { | |
int valPointer = 0; | |
while (true) { | |
// Before first -> end of search. | |
if (valPointer < 0) { | |
return; | |
} | |
// After last -> found a solution. | |
if (valPointer >= pow(SUDOKU_SIZE, 2)) { | |
cout << *this; | |
valPointer--; | |
continue; | |
} | |
value_type current = getIJ(valPointer); | |
value_type new_value = current + 1; | |
do { | |
setIJ(valPointer, new_value); | |
} while(!isValid() && ++new_value <= SUDOKU_SIZE); | |
if (new_value > SUDOKU_SIZE) { | |
setIJ(valPointer, 0); | |
valPointer--; | |
} else { | |
valPointer++; | |
} | |
} | |
} | |
ostream& operator<<(ostream& os, const SudokuMap& s) { | |
for (int i = 0; i < SUDOKU_SIZE; i++) { | |
for (int j = 0; j < SUDOKU_SIZE; j++) { | |
os << s.map[COORD_2_IDX(i, j)] << " "; | |
if (j % 3 == 2) { | |
os << ' '; | |
} | |
} | |
os << '\n'; | |
if (i % 3 == 2) { | |
os << '\n'; | |
} | |
} | |
return os << '\n'; | |
}; | |
int main(int argc, const char * argv[]) { | |
SudokuMap s; | |
s.solve(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment