Compare commits
2 Commits
8d50ac79d0
...
cc5210a71f
Author | SHA1 | Date | |
---|---|---|---|
cc5210a71f | |||
b5dfd9743a |
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
|||||||
CXX = g++
|
CXX = g++
|
||||||
CXXFLAGS = -Wall
|
CXXFLAGS = -Wall -O3
|
||||||
|
|
||||||
q: main.o
|
q: main.o
|
||||||
$(CXX) $(CXXFLAGS) -o q main.o
|
$(CXX) $(CXXFLAGS) -o q main.o
|
||||||
|
56
main.cpp
56
main.cpp
@ -15,15 +15,15 @@ class Board {
|
|||||||
public:
|
public:
|
||||||
int values[BOARD_SIZE];
|
int values[BOARD_SIZE];
|
||||||
|
|
||||||
int coordinates_to_id(int x, int y) {
|
inline int coordinates_to_id(int x, int y) {
|
||||||
return y * BOARD_DIMENSION + x;
|
return y * BOARD_DIMENSION + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get(int x, int y) {
|
inline int get(int x, int y) {
|
||||||
return values[coordinates_to_id(x, y)];
|
return values[coordinates_to_id(x, y)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(int x, int y, int value) {
|
inline void set(int x, int y, int value) {
|
||||||
values[coordinates_to_id(x, y)] = value;
|
values[coordinates_to_id(x, y)] = value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -39,33 +39,35 @@ public:
|
|||||||
|
|
||||||
Cell(Board *board, int x, int y) : board(board), x(x), y(y), value(board->get(x, y)) {}
|
Cell(Board *board, int x, int y) : board(board), x(x), y(y), value(board->get(x, y)) {}
|
||||||
|
|
||||||
void set_value(int new_value) {
|
inline void set_value(int new_value) {
|
||||||
value = new_value;
|
value = new_value;
|
||||||
update_possible_values();
|
update_possible_values();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_possible_values() {
|
void update_possible_values() {
|
||||||
// Start off with all possible numbers
|
// Start off with all possible numbers
|
||||||
std::list<int> possibilities{1, 2, 3, 4, 5, 6, 7, 8 ,9};
|
possible_values = {1, 2, 3, 4, 5, 6, 7, 8 ,9};
|
||||||
|
|
||||||
// Remove all from this row
|
// Remove all from this row
|
||||||
for (int dx = 0; dx < BOARD_DIMENSION; dx++) {
|
for (int dx = 0; dx < BOARD_DIMENSION; dx++) {
|
||||||
possibilities.remove(board->get(dx, y));
|
possible_values.remove(board->get(dx, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all from this column
|
// Remove all from this column
|
||||||
for (int dy = 0; dy < BOARD_DIMENSION; dy++) {
|
for (int dy = 0; dy < BOARD_DIMENSION; dy++) {
|
||||||
possibilities.remove(board->get(x, dy));
|
possible_values.remove(board->get(x, dy));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all from this quadrant
|
// Remove all from this quadrant
|
||||||
for (int dy = 0; dy < 3; dy++) {
|
for (int dy = 0; dy < 3; dy++) {
|
||||||
for (int dx = 0; dx < 3; dx++) {
|
for (int dx = 0; dx < 3; dx++) {
|
||||||
possibilities.remove(board->get((x - x % 3) + dx, (y - y % 3) + dy));
|
possible_values.remove(board->get((x - x % 3) + dx, (y - y % 3) + dy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
possible_values = possibilities;
|
bool operator<(const Cell &other) {
|
||||||
|
return possible_values.size() < other.possible_values.size();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -101,12 +103,7 @@ public:
|
|||||||
cell.update_possible_values();
|
cell.update_possible_values();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::make_heap(heap.begin(), heap.end(), sort_cells);
|
std::make_heap(heap.begin(), heap.end());
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Turn this into a member of Cell as opterator<
|
|
||||||
static bool sort_cells(const Cell& a, const Cell& b) {
|
|
||||||
return a.possible_values.size() < b.possible_values.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the possible values which a cell can take for every cell in the heap
|
// Update the possible values which a cell can take for every cell in the heap
|
||||||
@ -115,12 +112,31 @@ public:
|
|||||||
cell.update_possible_values();
|
cell.update_possible_values();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort_heap(heap.begin(), heap.end(), sort_cells);
|
std::sort_heap(heap.begin(), heap.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the possible values of all cells in the heap which are affected by
|
||||||
|
// the value of the cell at the given position
|
||||||
|
void update_affected_cells(int x, int y) {
|
||||||
|
int x_quadrant = x - x % 3;
|
||||||
|
int y_quadrant = y - y % 3;
|
||||||
|
|
||||||
|
for (Cell &cell : heap) {
|
||||||
|
if (cell.x == x // Column
|
||||||
|
|| cell.y == y // Row
|
||||||
|
|| (cell.x - cell.x % 3 == x_quadrant // Quadrant
|
||||||
|
&& cell.y - cell.y % 3 == y_quadrant)) {
|
||||||
|
|
||||||
|
cell.update_possible_values();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort_heap(heap.begin(), heap.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the best cell in the heap (the one with the most obvious choice)
|
// Returns the best cell in the heap (the one with the most obvious choice)
|
||||||
Cell get_next_best_empty_cell() {
|
Cell get_next_best_empty_cell() {
|
||||||
std::pop_heap(heap.begin(), heap.end(), sort_cells);
|
std::pop_heap(heap.begin(), heap.end());
|
||||||
Cell c = heap.back();
|
Cell c = heap.back();
|
||||||
heap.pop_back();
|
heap.pop_back();
|
||||||
|
|
||||||
@ -165,7 +181,7 @@ public:
|
|||||||
for (int value : cell.possible_values) {
|
for (int value : cell.possible_values) {
|
||||||
// Apply this value
|
// Apply this value
|
||||||
board->set(cell.x, cell.y, value);
|
board->set(cell.x, cell.y, value);
|
||||||
update_all_cells(); // TODO: We'd only need to re-rate the neighbours
|
update_affected_cells(cell.x, cell.y);
|
||||||
|
|
||||||
// Recurse; if we find a solution, we're done and can return true
|
// Recurse; if we find a solution, we're done and can return true
|
||||||
if (solve_recurse()) {
|
if (solve_recurse()) {
|
||||||
@ -174,12 +190,12 @@ public:
|
|||||||
|
|
||||||
// Seems like this was a dead end -- reset this move
|
// Seems like this was a dead end -- reset this move
|
||||||
board->set(cell.x, cell.y, 0);
|
board->set(cell.x, cell.y, 0);
|
||||||
update_all_cells(); // TODO: We could save and reuse the rating from before
|
update_affected_cells(cell.x, cell.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the cell back into the heap -- it couldn't be used for any valid solution, so we'll need it somewhere else later
|
// Put the cell back into the heap -- it couldn't be used for any valid solution, so we'll need it somewhere else later
|
||||||
heap.push_back(cell);
|
heap.push_back(cell);
|
||||||
std::push_heap(heap.begin(), heap.end(), sort_cells);
|
std::push_heap(heap.begin(), heap.end());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user