Su Doku
Su Doku (Japanese meaning number place) is the name given to a popular puzzle concept. Its origin is unclear, but credit must be attributed to Leonhard Euler who invented a similar, and much more difficult, puzzle idea called Latin Squares. The objective of Su Doku puzzles, however, is to replace the blanks (or zeros) in a 9 by 9 grid in such that each row, column, and 3 by 3 box contains each of the digits 1 to 9. Below is an example of a typical starting puzzle grid and its solution grid.

A well constructed Su Doku puzzle has a unique solution and can be solved by logic, although it may be necessary to employ "guess and test" methods in order to eliminate options (there is much contested opinion over this). The complexity of the search determines the difficulty of the puzzle; the example above is considered easy because it can be solved by straight forward direct deduction.
The 6K text file, sudoku.txt, contains fifty different Su Doku puzzles ranging in difficulty, but all with unique solutions (the first puzzle in the file is the example above).
By solving all fifty puzzles find the sum of the 3-digit numbers found in the top left corner of each solution grid; for example, 483 is the 3-digit number found in the top left corner of the solution grid above.
Implementations
#include <iostream>#include <fstream>#include <vector>#include <string>
bool is_valid(const std::vector<std::vector<int>>& grid, int row, int col, int num) { for (int i = 0; i < 9; ++i) { if (grid[row][i] == num || grid[i][col] == num) return false; } int box_row = (row / 3) * 3; int box_col = (col / 3) * 3; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (grid[box_row + i][box_col + j] == num) return false; } } return true;}
bool solve(std::vector<std::vector<int>>& grid) { for (int row = 0; row < 9; ++row) { for (int col = 0; col < 9; ++col) { if (grid[row][col] == 0) { for (int num = 1; num <= 9; ++num) { if (is_valid(grid, row, col, num)) { grid[row][col] = num; if (solve(grid)) return true; grid[row][col] = 0; } } return false; } } } return true;}
long long su_doku() { std::ifstream file("src/p096_sudoku.txt"); if (!file) return 0; long long sum = 0; std::string line; while (std::getline(file, line)) { if (line.substr(0, 4) == "Grid") continue; std::vector<std::vector<int>> grid(9, std::vector<int>(9)); // Parse the first line we already read for (int j = 0; j < 9; ++j) { grid[0][j] = line[j] - '0'; } // Read remaining 8 lines for (int i = 1; i < 9; ++i) { std::getline(file, line); for (int j = 0; j < 9; ++j) { grid[i][j] = line[j] - '0'; } } solve(grid); int num = grid[0][0] * 100 + grid[0][1] * 10 + grid[0][2]; sum += num; } return sum;}Solution Notes
Mathematical Background
Sudoku is a constraint satisfaction problem requiring each row, column, and 3x3 box to contain digits 1-9 exactly once. The problem involves solving 50 Sudoku puzzles and summing the 3-digit numbers from the top-left corner of each solution.
Algorithm Analysis
Backtracking solver tries numbers 1-9 in empty cells, validating row/column/box constraints. Recursively attempts placements until grid is filled or backtracks on invalid choices.
Performance
Extremely fast (~200ms in compiled languages) due to small grid size and efficient constraint checking. Python slower due to interpreted nature.
Key Insights
- Backtracking with early constraint validation avoids exploring invalid states
- File parsing handles puzzle format with grid headers
- Sum extraction from solved top-left corner
Educational Value
Demonstrates backtracking algorithms for NP-complete problems, file I/O in multiple languages, and constraint propagation techniques.
Problem #96 is taken from Project Euler and licensed under CC BY-NC-SA 4.0.