diff --git a/CMakeLists.txt b/CMakeLists.txt index a0907a8..78faeb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,5 +11,6 @@ endif() add_subdirectory(classic) add_subdirectory(constexpr) +add_subdirectory(constexpr_arr) add_subdirectory(qt) diff --git a/README.md b/README.md index 54991ae..793cded 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,19 @@ This is a quick shot implementation of a sudoku solver, used at starting point f ## constexpr This is the compile time variant. Works for me with clang 3.6, needs C++14 (constexpr using "if" and loops). +## constexpr_arr +This is a modification of the constexpr example using builtin array instead of std::array. We had a +longer discussion in our local c++ user group about the fact, that c++14 removed the implicit const +from constexpr methods. This is the result of our search for a use case. And it simplifies the +implemention by removing the template-gymnastics used in the constexpr example to "modify" values +in a std::array. Courtesy goes to [Arne Metz](http://arne-mertz.de/category/cpp/new-features/) + ## qt This is just a graphical frontend to demonstrate the problem and visualize how backtracking works. See also [my blog](http://www.valpo.de/?p=190) + +# Compiler +Examples tested with clang (3.6 and current version from svn) and gcc 5.2.1. Clang needs around 5 minutes to +compile one constexpr example and uses around 100MB of memory. gcc needs around 388GB of memory for the +constexpr example, so do not forget to add some memory before compiling. diff --git a/constexpr/CMakeLists.txt b/constexpr/CMakeLists.txt index 7ff4eea..6c3d182 100644 --- a/constexpr/CMakeLists.txt +++ b/constexpr/CMakeLists.txt @@ -1,6 +1,5 @@ aux_source_directory(. SRC_LIST) # -ftemplate-backtrace-limit=0 add_executable(constexpr_sudoku ${SRC_LIST}) -#target_link_libraries(constexpr_sudoku c++ c++abi) diff --git a/constexpr_arr/CMakeLists.txt b/constexpr_arr/CMakeLists.txt new file mode 100644 index 0000000..e526212 --- /dev/null +++ b/constexpr_arr/CMakeLists.txt @@ -0,0 +1,5 @@ +aux_source_directory(. SRC_LIST) +# -ftemplate-backtrace-limit=0 +add_executable(constexpr_arr_sudoku ${SRC_LIST}) + + diff --git a/constexpr_arr/main.cpp b/constexpr_arr/main.cpp new file mode 100644 index 0000000..8d450f9 --- /dev/null +++ b/constexpr_arr/main.cpp @@ -0,0 +1,162 @@ +//#include +//#include +#include +#include +#include + +#include + +using std::cout; +using std::endl; + +constexpr int sqrt_impl(int i, int val) +{ + return i*i == val ? i : sqrt_impl(i-1,val); +} +constexpr int sqrt(int i) +{ + return sqrt_impl(i,i); +} + +// sudoku (== matrix) class +template +class SudokuT +{ +private: +public: + T data[N*N]; + constexpr unsigned operator()(size_t row, size_t col) const { + return row*N+col >= N*N ? 0 + : data[row*N+col]; + } + constexpr SudokuT replace(size_t row, size_t col, T val) { + data[row*N+col] = val; + return *this; + } + constexpr size_t dimension() const { return N; } +}; + +using Sudoku = SudokuT; +using Cell = std::pair; + +std::ostream& operator<<(std::ostream& os, const Sudoku& s) { + os << "+------------------+\n"; + for(size_t i=0; i< s.dimension(); ++i) { + os << "|"; + for(size_t j=0; j< s.dimension(); ++j) { + os << s(i,j) << " "; + } + os << "|\n"; + } + os << "+------------------+\n"; + return os; +} + +std::ostream& operator<<(std::ostream& os, const Cell& c) +{ + os << '(' << c.first << ',' << c.second << ')'; + return os; +} + +constexpr bool rowValid(const Sudoku& s, size_t row, size_t pos = 0) +{ + if (pos > s.dimension()) return true; + else if (s(row,pos) == 0) return rowValid(s,row,pos+1); + else { + for(size_t i=pos+1;i s.dimension()) return true; + else if (s(pos,col) == 0) return colValid(s,col,pos+1); + else { + for(size_t i=pos+1;i s.dimension()) return true; + else if (qVal(s, x,y,pos) == 0) return quadrantValid(s, x, y, pos+1); + else { + for(size_t i=pos+1;i::max(),std::numeric_limits::max()}; +} + +constexpr Sudoku solve(const Sudoku& s) +{ + if (!valid(s)) return s; + else { + const Cell n{next(s)}; + if (n.first == std::numeric_limits::max()) return s; + for(unsigned i=1;i<=s.dimension();++i) { + const auto ns = Sudoku(s).replace(n.first,n.second,i); + const auto res = solve(ns); + if (finished(res) && valid(res)) return res; + } + return s; + } +} + +int main() +{ + constexpr Sudoku sudoku{ + { + 9, 5, 0, 0, 2, 0, 0, 0, 0, + 0, 7, 8, 5, 0, 0, 0, 0, 0, + 0, 6, 0, 4, 0, 0, 0, 0, 0, + 0, 9, 0, 7, 3, 0, 0, 5, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 1, 0, 0, 8, 5, 0, 6, 0, + 0, 0, 0, 0, 0, 6, 0, 8, 0, + 0, 0, 0, 0, 0, 8, 7, 9, 0, + 0, 0, 0, 0, 7, 0, 0, 3, 1, + } + }; + cout << sudoku << endl; + constexpr Sudoku res = solve(sudoku); + cout << res << endl; + return valid(res) && finished(res) ? 0 : 1; +}