Commit 6d225eea authored by nogzer's avatar nogzer

Init

parents
# sudoku
Simple command-line program in C++ to solve a grid of standard sudoku game
038000000
009540020
600091075
283100706
000000000
901006352
450210008
090084500
000000260
CXX = g++
CXXFLAGS = -Wall -Wextra
SRC = ./src/*.cpp ./src/*.hpp
EXEC = sudoku
$(EXEC) : $(SRC)
$(CXX) $(CXXFLAGS) -o $@ $^
#include "entity.hpp"
/*!
* \file entity.cpp
* \brief Implementation of class Entity
* \author Matthieu Nogatchewsky
* \version 1.0
* \date April 2018
*/
Entity::Entity(){
initEntity();
}
void Entity::initEntity(){
for(Numerous i = 0 ; i < 9 ; i++){
values[i] = true;
}
}
bool Entity::addValue(Numerous v){
if(v>=1 && v<=9){
if(values[v-1]){
values[v-1] = false;
return true;
}
}
return false;
}
List* Entity::getList(){
List* l = new List();
for(Numerous i = 0 ; i < 9 ; i++){
if(values[i]){
l->push(i+1);
}
}
return l;
}
void Entity::remValue(Numerous v){
values[v-1] = true;
}
#ifndef DEF_ENTITY
#define DEF_ENTITY
/*!
* \file entity.hpp
* \brief Entity class is used to check the constraints of sudoku game
*
* It can be used to represent rows, columns or squares
* \author Matthieu Nogatchewsky
* \version 1.0
* \date April 2018
*/
#include "list.hpp"
/*!
* \class Entity
* \brief Class which represents an entity
*/
class Entity{
public :
/*!
* \brief Constructor
*/
Entity();
/*!
* \brief Initialize the entity
*/
void initEntity();
/*!
* \brief Set a value as used
* \param v Value to set as used
* \return Test if the value has not been set before
*/
bool addValue(Numerous v);
/*!
* \brief Get the free values
* \return List which contains the free values
*/
List* getList();
/*!
* \brief Set a value as unused
* \param v Value to set as unused
*/
void remValue(Numerous v);
private :
bool values[9]; /*!< Indicates if each value is used */
};
#endif
#include "grid.hpp"
/*!
* \file grid.cpp
* \brief Implementation of class Grid
* \author Matthieu Nogatchewsky
* \version 1.0
* \date April 2018
*/
Grid::Grid(){
initGrid();
}
void Grid::initGrid(){
position = 0;
state = PROCESSING;
for(Numerous j = 0 ; j < 9 ; j++){
row[j].initEntity();
column[j].initEntity();
square[j].initEntity();
}
for(Numerous i = 0 ; i < 81 ; i++){
cells[i%9][i/9]=0;
}
}
bool Grid::load(Board extCells){
initGrid();
Numerous value;
for(Numerous i = 0 ; i < 81 && (state == PROCESSING) ; i++){
value = extCells[i%9][i/9];
if(value >= 1 && value <= 9){
nextStep(value);
} else {
nextCell();
}
}
initCell();
return (state != UNSOLVABLE);
}
void Grid::save(Board& extCells){
for(Numerous i = 0 ; i < 81 ; i++){
extCells[i%9][i/9] = cells[i%9][i/9];
}
}
void Grid::initCell(){
position = 0;
}
void Grid::nextCell(){
position++;
}
void Grid::prevCell(){
position--;
}
void Grid::nextStep(Numerous value){
bool passed = true;
passed &= row[theRow()].addValue(value);
passed &= column[theColumn()].addValue(value);
passed &= square[theSquare()].addValue(value);
if(passed){
cells[theRow()][theColumn()] = value;
nextCell();
} else {
state = UNSOLVABLE;
}
}
void Grid::prevStep(Numerous value){
prevCell();
cells[theRow()][theColumn()] = 0;
square[theSquare()].remValue(value);
column[theColumn()].remValue(value);
row[theRow()].remValue(value);
}
void Grid::processing(){
if(position == 81){
state = SOLVED;
} else {
if(cells[theRow()][theColumn()] == 0){
List l = List();
l.merge(row[theRow()].getList());
l.merge(column[theColumn()].getList());
l.merge(square[theSquare()].getList());
if(!l.empty()){
for(Numerous i = 0 ; i < l.size() && (state == PROCESSING) ; i++){
nextStep(l.at(i));
processing();
if(state == PROCESSING) {
prevStep(l.at(i));
}
}
}
} else {
nextCell();
processing();
prevCell();
}
}
}
void Grid::solve(){
initCell();
state = PROCESSING;
processing();
if(state == PROCESSING){
state = UNSOLVABLE;
}
}
Numerous Grid::theSquare(){
return ((position%9)/3+((position/9)/3)*3);
}
Numerous Grid::theColumn(){
return position/9;
}
Numerous Grid::theRow(){
return position%9;
}
#ifndef DEF_GRID
#define DEF_GRID
#include "entity.hpp"
/*!
* \file grid.hpp
* \brief Grid of standard sudoku game
* \author Matthieu Nogatchewsky
* \version 1.0
* \date April 2018
*/
typedef Numerous Board[9][9];
/*!
* \class Grid
* \brief Class of a grid
*/
class Grid{
public :
/*!
* Constructor
*/
Grid();
/*!
* \brief Initialize the grid
*/
void initGrid();
/*!
* \brief Load internal board from external board
* \param extCells External board to load
*/
bool load(Board extCells);
/*!
* \brief Save internal board into external board
* \param extCells External Board in which to save
*/
void save(Board &extCells);
/*!
* \brief Initialize the position in the grid
*/
void initCell();
/*!
* \brief Increase the position
*/
void nextCell();
/*!
* \brief Decrease the position
*/
void prevCell();
/*!
* \brief Move a step forward during the process
* \param v Value to put inside the current cell
*/
void nextStep(Numerous v);
/*!
* \brief Move a step before during the process
* \param v Value to remove from the current cell
*/
void prevStep(Numerous v);
/*!
* \brief Recursive helper for the solve method
*/
void processing();
/*!
* \brief Solve the grid
*/
void solve();
/*!
* \brief Get the square of the current cell
* \return Number of the current square
*/
Numerous theSquare();
/*!
* \brief Get the column of the current cell
* \return Number of the current column
*/
Numerous theColumn();
/*!
* \brief Get the row of the current cell
* \return Number of the current row
*/
Numerous theRow();
private :
Numerous position; /*!< Position on the grid (from top to bottom and left to right)*/
enum State {
PROCESSING,
SOLVED,
UNSOLVABLE
} state ; /*!< State of the grid */
Board cells; /*!< Internal board of the grid */
Entity row[9]; /*!< Rows of the grid */
Entity column[9]; /*!< Columns of the grid */
Entity square[9]; /*!< Squares of the grid */
};
#endif
#include "list.hpp"
/*!
* \file list.cpp
* \brief Implementation of class List
* \author Matthieu Nogatchewsky
* \version 1.0
* \date April 2018
*/
List::List() : blank(true) {
values = new SubList();
};
List::~List(){
delete values;
}
void List::merge(List* l){
if(blank){
for(int i = 0 ; i < l->size() ; i++){
values->push_back(l->at(i));
}
blank = false;
} else {
SubList* t = new SubList();
Numerous m(0), n(0);
while( m < size() && n < l->size() ){
if(at(m) < l->at(n)){
m++;
} else if(at(m) > l->at(n)){
n++;
} else {
t->push_back(at(m));
m++; n++;
}
}
delete values;
values = t;
}
delete l;
}
void List::push(Numerous v){
values->push_back(v);
}
Numerous List::at(Numerous i){
return values->at(i);
}
Numerous List::size(){
return values->size();
}
bool List::empty(){
return (values->size() == 0);
}
#ifndef DEF_LIST
#define DEF_LIST
/*!
* \file list.hpp
* \brief List of values with specifics methods
* \author Matthieu Nogatchewsky
* \version 1.0
* \date April 2018
*/
#include <vector>
typedef unsigned char Numerous;
typedef std::vector<Numerous> SubList;
/*!
* \class List
* \brief Class for list implementation
*/
class List{
public :
/*!
* \brief Constructor
*/
List();
/*!
* \brief Destructor
*/
~List();
/*!
* \brief Find commons values with another list
* \param l Another list to merge
*/
void merge(List* l);
/*!
* \brief Push a value in the list
* \param v Value to push
*/
void push(Numerous v);
/*!
* \brief Get value in list
* \param i Index of value to get
*/
Numerous at(Numerous i);
/*!
* \brief Get size of list
* \return Size of list
*/
Numerous size();
/*!
* \brief Test if list is empty
* \return Result of test
*/
bool empty();
private :
SubList* values; /*!< Values of list */
bool blank; /*!< Test if list has not been initialized */
};
#endif
#include <iostream>
#include <fstream>
#include "grid.hpp"
using namespace std;
/*!
* \file main.cpp
* \brief Standard Sudoku Game Solver
*
* Little program which solves a grid of standard sudoku game
* from a formatted text file which contains the grid's values.
*
* \author Matthieu Nogatchewsky
* \version 1.0
* \date April 2018
*/
/*!
* \fn void display(Board cells)
* \brief Display a board on terminal
* \param cells Board to display
*/
void display(Board cells);
/*!
* \fn void loadFile(Board &cells, char* dir)
* \bried Load a board from a formatted text file
* \param cells Board to load
* \param dir Dired
*/
void loadFile(Board &cells, char* dir);
/*!
* \fn int main()
* \brief Program's entry
*/
int main(int argc, char** argv){
if(argc == 2){
Board cells4;
loadFile(cells4, argv[1]);
display(cells4);
Grid g = Grid();
if(g.load(cells4)){
g.solve();
g.save(cells4);
display(cells4);
}
}
return 0;
}
void display(Board cells){
for(Numerous i = 0 ; i < 9 ; i++){
cout << "\n";
for(Numerous j = 0 ; j < 9 ; j++){
cout << (char) (cells[i][j]+'0');
}
}
cout << endl;
}
void loadFile(Board &cells, char* dir){
ifstream file(dir);
Numerous i(0);
string chain("");
while(getline(file, chain) && i < 9){
for(Numerous j = 0 ; j < 9 ; j++){
cells[i][j] = (chain[j]-48);
}
i++;
}
file.close();
}
File added
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment