Loading grids/easy/metro-224 0 → 100644 +9 −0 Original line number Diff line number Diff line 0 6 0 3 0 0 0 0 7 0 0 0 1 0 0 0 5 9 8 7 0 9 0 0 0 0 0 0 9 0 6 5 0 2 0 1 0 0 0 0 0 0 0 0 0 5 0 1 0 2 7 0 4 0 0 0 0 0 0 6 0 3 2 3 8 0 0 0 4 0 0 0 4 0 0 0 0 9 0 6 0 grids/easy/metro-225 0 → 100644 +9 −0 Original line number Diff line number Diff line 3 0 0 6 1 2 0 0 9 0 0 0 0 0 8 6 0 0 0 6 9 4 0 0 8 0 0 1 9 0 2 0 6 7 0 4 5 0 0 0 0 0 0 0 6 6 0 8 9 0 7 0 1 2 0 0 1 0 0 5 3 4 0 0 0 6 8 0 0 0 0 0 8 0 0 3 2 9 0 0 7 src/block.hxx +27 −11 Original line number Diff line number Diff line #ifndef BLOCK_HXX_ # define BLOCK_HXX_ inline Block::Block() { Block(0); } inline Block::Block(int value) { inline Block::Block(int value = 0) { value_ = value; for (int i = 0; i < GRID_SIDE; ++i) forbidden_[i] = false; } inline bool Block::is_forbidden(int value) const { assert(value > 0 && value <= GRID_SIDE); if (!(value > 0 && value <= GRID_SIDE)) throw std::string("Invalid is_forbidden value"); return forbidden_[value - 1]; } Loading @@ -21,22 +17,32 @@ inline bool Block::is_set() const { return value_ != 0; } inline int Block::value_get() const inline int Block::get() const { return value_; } inline void Block::set(int val) { assert(val > 0 && val <= GRID_SIDE); if (!(val > 0 && val <= GRID_SIDE)) throw std::string("Invalid value"); if (value_ != 0) throw std::string("Value already set"); if (forbidden_[val - 1]) throw std::string("Set a forbidden value"); value_ = val; for (int i = 0; i < GRID_SIDE; ++i) for (register int i = 0; i < GRID_SIDE; ++i) forbidden_[i] = true; } inline void Block::forbid(int val) { assert(val > 0 && val <= GRID_SIDE); if (!(val > 0 && val <= GRID_SIDE)) throw std::string("Invalid forbid value"); if (value_ != 0) throw std::string("Try to forbid whereas case is set"); forbidden_[val - 1] = true; if (forbidden_count() == GRID_SIDE) throw std::string("All possibilities are forbidden."); } inline std::ostream &operator<<(std::ostream &stream, const Block &blk) { Loading @@ -47,4 +53,14 @@ inline std::ostream &operator<<(std::ostream &stream, const Block &blk) { return stream; } inline int Block::forbidden_count() const { int count = 0; for (int i = 0; i < GRID_SIDE; ++i) if (forbidden_[i]) ++count; return count; } #endif src/grid.cc +61 −15 Original line number Diff line number Diff line Loading @@ -17,15 +17,12 @@ int Grid::load(const char *filename) for (int y = 0; y < GRID_SIDE; ++y) for (int x = 0; x < GRID_SIDE; ++x) { fs >> std::dec >> val; // if (val > 0) // std::cout << "(" << x << "," << y << ")" << " " << val << std::endl; if (val < 0 || val > 9) { std::cerr << "Invalid value in file: " << val << std::endl; exit(EXIT_LOADFAIL); } if (val > 0) pose(x, y, val); //block_[i][j].set(val); } fs.close(); return 1; Loading @@ -45,20 +42,67 @@ void Grid::pose(int x, int y, int v) std::cerr << "Double positionning: " << x << ", " << y << std::endl; exit(EXIT_INV_VAL); } try { block_[x][y].set(v); } catch (std::string s) { std::cerr << "Unable to pose " << v << " in (" << x << "," << y << "): " << s << std::endl; throw 2; } for (int i = 0; i < GRID_SIDE; ++i) { try { block_[x][i].forbid(v); } catch (std::string s) { std::cerr << "Unable to forbid " << v << " in (" << x << "," << y << "): " << s << std::endl; } try { block_[i][y].forbid(v); } catch (std::string s) { std::cerr << "Unable to forbid " << v << " in (" << x << "," << y << "): " << s << std::endl; } } for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) { std::cout << "forbid x:"<< x << ", y:" << y << ",i:" <<i <<",j;" <<j <<std::endl; block_[(x / 3) * 3 + i][(y / 3) * 3 + j].forbid(v); } } void Grid::resolve() { int posed; if (Grid::verbose) std::cout << "Resolving..." << std::endl; do { posed = 0; for (int y = 0; y < GRID_SIDE; ++y) for (int x = 0; x < GRID_SIDE; ++x) { if (block_[x][y].is_set()) continue; //check for complete block int count = 0, lastval; for (int i = 1; i <= GRID_SIDE; ++i) if (!block_[x][y].is_forbidden(i)) { ++count; lastval = i; } if (count == 1) { pose(x, y, lastval); if (Grid::verbose) std::cout << "posed " << lastval << " to " << x << ","<< y << std::endl; ++posed; } } } while (posed > 0); } void Grid::print() const Loading @@ -76,7 +120,7 @@ void Grid::print() const std::cout << "| "; std::cout << "|"; for (int j = i * 3 + 1; j <= i * 3 + 3; ++j) if (block_[x][y].value_get() == j) if (block_[x][y].get() == j) std::cout << "\033[0;32m" << j << "\033[0m"; else if (block_[x][y].is_forbidden(j)) std::cout << "\033[0;31m" << j << "\033[0m"; Loading @@ -102,7 +146,7 @@ bool Grid::is_done() const { for (int i = 0; i < GRID_SIDE; ++i) for (int j = 0; j < GRID_SIDE; ++j) if (block_[i][j].value_get() == 0) if (block_[i][j].get() == 0) return false; return true; } Loading @@ -119,12 +163,12 @@ bool Grid::verify() const horizontal_line[j] = vertical_line[j] = false; for (int j = 0; j < GRID_SIDE; ++j) { //horizontals tmp = block_[i][j].value_get() - 1; tmp = block_[i][j].get() - 1; if (tmp < 0 || horizontal_line[tmp]) return false; horizontal_line[tmp] = true; //verticals tmp = block_[j][i].value_get() - 1; tmp = block_[j][i].get() - 1; if (tmp < 0 || vertical_line[tmp] == true) return false; vertical_line[tmp] = true; Loading @@ -133,6 +177,7 @@ bool Grid::verify() const if (!vertical_line[j] || !horizontal_line[j]) return false; } std::cout << "sex" << std::endl; // check nine blocks (use vertical_block) for (int j = 0; j < GRID_SIDE; ++j) vertical_line[j] = false; Loading @@ -140,11 +185,12 @@ bool Grid::verify() const for (int j = 0; j < GRID_SIDE; j += 3) for (int k = 0; k < 3; ++k) for (int l = 0; l < 3; ++l) { tmp = block_[i + k][j + l].value_get() - 1; tmp = block_[i + k][j + l].get() - 1; if (tmp < 0 || vertical_line[tmp] == true) return false; vertical_line[tmp] = true; } std::cout << "city" << std::endl; for (int j = 0; j < GRID_SIDE; ++j) if (!vertical_line[j]) return false; Loading src/sudoku.cc +27 −14 Original line number Diff line number Diff line #include <stdlib.h> #include <unistd.h> #include "sudoku.hh" inline static void usage(); int main(int argc, char *argv[]) { int found; int opt; if (argc != 2 && argc !=3) { std::cerr << "Usage: sudoku [-v] file" << std::endl; return EXIT_USAGE; if (argc != 2 && argc !=3) usage(); while ((opt = getopt(argc, argv, "vx")) != -1) switch (opt) { case 'v': Grid::verbose = true; break; case 'x': Grid::advprint = true; break; default: usage(); } if (argc == 3 && argv[1] == (std::string) "-v") Grid::verbose = true; if (argc == 3 && argv[1] == (std::string) "-p") Grid::advprint = true; Grid *grid = new Grid(); if (!grid->load(argv[Grid::verbose || Grid::advprint ? 2 : 1])) { if (!grid->load(argv[optind])) { std::cerr << "Loading failed !" << std::endl; return EXIT_LOADFAIL; } Loading @@ -23,10 +26,20 @@ int main(int argc, char *argv[]) grid->print(); } grid->resolve(); found = grid->verify() ? EXIT_FOUND : EXIT_NOTFOUND; if (found == EXIT_FOUND && Grid::verbose > 0) std::cout << "Solution found." << std::endl; grid->print(); return found; if (grid->verify()) { if (Grid::verbose) std::cout << "Solution found." << std::endl; return EXIT_FOUND; } std::cout << "No suitable solution found." << std::endl; return EXIT_NOTFOUND; } inline static void usage() { std::cerr << "Usage: sudoku [-vx] file" << std::endl; std::cerr << "Options: -v: Verbose mode" << std::endl; std::cerr << " -x: eXtended print mode" << std::endl; exit(EXIT_USAGE); } Loading
grids/easy/metro-224 0 → 100644 +9 −0 Original line number Diff line number Diff line 0 6 0 3 0 0 0 0 7 0 0 0 1 0 0 0 5 9 8 7 0 9 0 0 0 0 0 0 9 0 6 5 0 2 0 1 0 0 0 0 0 0 0 0 0 5 0 1 0 2 7 0 4 0 0 0 0 0 0 6 0 3 2 3 8 0 0 0 4 0 0 0 4 0 0 0 0 9 0 6 0
grids/easy/metro-225 0 → 100644 +9 −0 Original line number Diff line number Diff line 3 0 0 6 1 2 0 0 9 0 0 0 0 0 8 6 0 0 0 6 9 4 0 0 8 0 0 1 9 0 2 0 6 7 0 4 5 0 0 0 0 0 0 0 6 6 0 8 9 0 7 0 1 2 0 0 1 0 0 5 3 4 0 0 0 6 8 0 0 0 0 0 8 0 0 3 2 9 0 0 7
src/block.hxx +27 −11 Original line number Diff line number Diff line #ifndef BLOCK_HXX_ # define BLOCK_HXX_ inline Block::Block() { Block(0); } inline Block::Block(int value) { inline Block::Block(int value = 0) { value_ = value; for (int i = 0; i < GRID_SIDE; ++i) forbidden_[i] = false; } inline bool Block::is_forbidden(int value) const { assert(value > 0 && value <= GRID_SIDE); if (!(value > 0 && value <= GRID_SIDE)) throw std::string("Invalid is_forbidden value"); return forbidden_[value - 1]; } Loading @@ -21,22 +17,32 @@ inline bool Block::is_set() const { return value_ != 0; } inline int Block::value_get() const inline int Block::get() const { return value_; } inline void Block::set(int val) { assert(val > 0 && val <= GRID_SIDE); if (!(val > 0 && val <= GRID_SIDE)) throw std::string("Invalid value"); if (value_ != 0) throw std::string("Value already set"); if (forbidden_[val - 1]) throw std::string("Set a forbidden value"); value_ = val; for (int i = 0; i < GRID_SIDE; ++i) for (register int i = 0; i < GRID_SIDE; ++i) forbidden_[i] = true; } inline void Block::forbid(int val) { assert(val > 0 && val <= GRID_SIDE); if (!(val > 0 && val <= GRID_SIDE)) throw std::string("Invalid forbid value"); if (value_ != 0) throw std::string("Try to forbid whereas case is set"); forbidden_[val - 1] = true; if (forbidden_count() == GRID_SIDE) throw std::string("All possibilities are forbidden."); } inline std::ostream &operator<<(std::ostream &stream, const Block &blk) { Loading @@ -47,4 +53,14 @@ inline std::ostream &operator<<(std::ostream &stream, const Block &blk) { return stream; } inline int Block::forbidden_count() const { int count = 0; for (int i = 0; i < GRID_SIDE; ++i) if (forbidden_[i]) ++count; return count; } #endif
src/grid.cc +61 −15 Original line number Diff line number Diff line Loading @@ -17,15 +17,12 @@ int Grid::load(const char *filename) for (int y = 0; y < GRID_SIDE; ++y) for (int x = 0; x < GRID_SIDE; ++x) { fs >> std::dec >> val; // if (val > 0) // std::cout << "(" << x << "," << y << ")" << " " << val << std::endl; if (val < 0 || val > 9) { std::cerr << "Invalid value in file: " << val << std::endl; exit(EXIT_LOADFAIL); } if (val > 0) pose(x, y, val); //block_[i][j].set(val); } fs.close(); return 1; Loading @@ -45,20 +42,67 @@ void Grid::pose(int x, int y, int v) std::cerr << "Double positionning: " << x << ", " << y << std::endl; exit(EXIT_INV_VAL); } try { block_[x][y].set(v); } catch (std::string s) { std::cerr << "Unable to pose " << v << " in (" << x << "," << y << "): " << s << std::endl; throw 2; } for (int i = 0; i < GRID_SIDE; ++i) { try { block_[x][i].forbid(v); } catch (std::string s) { std::cerr << "Unable to forbid " << v << " in (" << x << "," << y << "): " << s << std::endl; } try { block_[i][y].forbid(v); } catch (std::string s) { std::cerr << "Unable to forbid " << v << " in (" << x << "," << y << "): " << s << std::endl; } } for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) { std::cout << "forbid x:"<< x << ", y:" << y << ",i:" <<i <<",j;" <<j <<std::endl; block_[(x / 3) * 3 + i][(y / 3) * 3 + j].forbid(v); } } void Grid::resolve() { int posed; if (Grid::verbose) std::cout << "Resolving..." << std::endl; do { posed = 0; for (int y = 0; y < GRID_SIDE; ++y) for (int x = 0; x < GRID_SIDE; ++x) { if (block_[x][y].is_set()) continue; //check for complete block int count = 0, lastval; for (int i = 1; i <= GRID_SIDE; ++i) if (!block_[x][y].is_forbidden(i)) { ++count; lastval = i; } if (count == 1) { pose(x, y, lastval); if (Grid::verbose) std::cout << "posed " << lastval << " to " << x << ","<< y << std::endl; ++posed; } } } while (posed > 0); } void Grid::print() const Loading @@ -76,7 +120,7 @@ void Grid::print() const std::cout << "| "; std::cout << "|"; for (int j = i * 3 + 1; j <= i * 3 + 3; ++j) if (block_[x][y].value_get() == j) if (block_[x][y].get() == j) std::cout << "\033[0;32m" << j << "\033[0m"; else if (block_[x][y].is_forbidden(j)) std::cout << "\033[0;31m" << j << "\033[0m"; Loading @@ -102,7 +146,7 @@ bool Grid::is_done() const { for (int i = 0; i < GRID_SIDE; ++i) for (int j = 0; j < GRID_SIDE; ++j) if (block_[i][j].value_get() == 0) if (block_[i][j].get() == 0) return false; return true; } Loading @@ -119,12 +163,12 @@ bool Grid::verify() const horizontal_line[j] = vertical_line[j] = false; for (int j = 0; j < GRID_SIDE; ++j) { //horizontals tmp = block_[i][j].value_get() - 1; tmp = block_[i][j].get() - 1; if (tmp < 0 || horizontal_line[tmp]) return false; horizontal_line[tmp] = true; //verticals tmp = block_[j][i].value_get() - 1; tmp = block_[j][i].get() - 1; if (tmp < 0 || vertical_line[tmp] == true) return false; vertical_line[tmp] = true; Loading @@ -133,6 +177,7 @@ bool Grid::verify() const if (!vertical_line[j] || !horizontal_line[j]) return false; } std::cout << "sex" << std::endl; // check nine blocks (use vertical_block) for (int j = 0; j < GRID_SIDE; ++j) vertical_line[j] = false; Loading @@ -140,11 +185,12 @@ bool Grid::verify() const for (int j = 0; j < GRID_SIDE; j += 3) for (int k = 0; k < 3; ++k) for (int l = 0; l < 3; ++l) { tmp = block_[i + k][j + l].value_get() - 1; tmp = block_[i + k][j + l].get() - 1; if (tmp < 0 || vertical_line[tmp] == true) return false; vertical_line[tmp] = true; } std::cout << "city" << std::endl; for (int j = 0; j < GRID_SIDE; ++j) if (!vertical_line[j]) return false; Loading
src/sudoku.cc +27 −14 Original line number Diff line number Diff line #include <stdlib.h> #include <unistd.h> #include "sudoku.hh" inline static void usage(); int main(int argc, char *argv[]) { int found; int opt; if (argc != 2 && argc !=3) { std::cerr << "Usage: sudoku [-v] file" << std::endl; return EXIT_USAGE; if (argc != 2 && argc !=3) usage(); while ((opt = getopt(argc, argv, "vx")) != -1) switch (opt) { case 'v': Grid::verbose = true; break; case 'x': Grid::advprint = true; break; default: usage(); } if (argc == 3 && argv[1] == (std::string) "-v") Grid::verbose = true; if (argc == 3 && argv[1] == (std::string) "-p") Grid::advprint = true; Grid *grid = new Grid(); if (!grid->load(argv[Grid::verbose || Grid::advprint ? 2 : 1])) { if (!grid->load(argv[optind])) { std::cerr << "Loading failed !" << std::endl; return EXIT_LOADFAIL; } Loading @@ -23,10 +26,20 @@ int main(int argc, char *argv[]) grid->print(); } grid->resolve(); found = grid->verify() ? EXIT_FOUND : EXIT_NOTFOUND; if (found == EXIT_FOUND && Grid::verbose > 0) std::cout << "Solution found." << std::endl; grid->print(); return found; if (grid->verify()) { if (Grid::verbose) std::cout << "Solution found." << std::endl; return EXIT_FOUND; } std::cout << "No suitable solution found." << std::endl; return EXIT_NOTFOUND; } inline static void usage() { std::cerr << "Usage: sudoku [-vx] file" << std::endl; std::cerr << "Options: -v: Verbose mode" << std::endl; std::cerr << " -x: eXtended print mode" << std::endl; exit(EXIT_USAGE); }