Update only cells affected by change
+ some more minor optimizations
This commit is contained in:
		
							parent
							
								
									b5dfd9743a
								
							
						
					
					
						commit
						cc5210a71f
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@ -1,5 +1,5 @@
 | 
			
		||||
CXX = g++
 | 
			
		||||
CXXFLAGS = -Wall
 | 
			
		||||
CXXFLAGS = -Wall -O3
 | 
			
		||||
 | 
			
		||||
q: main.o
 | 
			
		||||
	$(CXX) $(CXXFLAGS) -o q main.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								main.cpp
									
									
									
									
									
								
							@ -15,15 +15,15 @@ class Board {
 | 
			
		||||
public:
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int get(int x, int y) {
 | 
			
		||||
    inline int get(int x, int 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;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@ -39,33 +39,31 @@ public:
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
        update_possible_values();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void update_possible_values() {
 | 
			
		||||
        // 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
 | 
			
		||||
        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
 | 
			
		||||
        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
 | 
			
		||||
        for (int dy = 0; dy < 3; dy++) {
 | 
			
		||||
            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) {
 | 
			
		||||
@ -117,6 +115,25 @@ public:
 | 
			
		||||
        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)
 | 
			
		||||
    Cell get_next_best_empty_cell() {
 | 
			
		||||
		std::pop_heap(heap.begin(), heap.end());
 | 
			
		||||
@ -164,7 +181,7 @@ public:
 | 
			
		||||
        for (int value : cell.possible_values) {
 | 
			
		||||
            // Apply this 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
 | 
			
		||||
            if (solve_recurse()) {
 | 
			
		||||
@ -173,7 +190,7 @@ public:
 | 
			
		||||
 | 
			
		||||
            // Seems like this was a dead end -- reset this move
 | 
			
		||||
            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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user