From 756a8c48b567901d2483e6ea2213c00e5ca47931 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Fri, 28 Oct 2016 23:14:38 +0200 Subject: Initial --- .gitignore | 4 + Makefile | 24 ++++++ easy.txt | 11 +++ easy2.txt | 11 +++ eureka.txt | 19 +++++ solve.cpp | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 344 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 easy.txt create mode 100644 easy2.txt create mode 100644 eureka.txt create mode 100644 solve.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af2ead4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +solve +*.o +*.dSYM +.DS_Store diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ef6cc85 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +CXX = g++ +CXXFLAGS = -Wall -Wextra -std=c++11 -fwrapv -g +ifneq ($(DEBUG),) + CXXFLAGS += -g +else + CXXFLAGS += -O2 +endif +BIN = solve + +.PHONY: all clean remake + +all: $(BIN) + +clean: + rm -rf $(BIN) *.o *.dSYM + +remake: clean all + + +$(BIN): $(patsubst %.cpp,%.o,$(wildcard *.cpp)) + $(CXX) -o $@ $^ + +%.o: %.cpp $(wildcard *.h) + $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/easy.txt b/easy.txt new file mode 100644 index 0000000..5acd093 --- /dev/null +++ b/easy.txt @@ -0,0 +1,11 @@ +. . . . 4 6 1 . . +3 . . . . . . . . +7 6 . . . 3 . 5 2 + +. 7 1 3 . . . . 8 +9 3 . . 2 . . 7 1 +6 . . . . 1 5 4 . + +1 8 . 6 . . . 9 4 +. . . . . . . . 7 +. . 7 4 1 . . . . diff --git a/easy2.txt b/easy2.txt new file mode 100644 index 0000000..88f4eaa --- /dev/null +++ b/easy2.txt @@ -0,0 +1,11 @@ +. 6 . . . 4 3 . . +. 8 . . 2 . . . . +. . 2 . 7 9 8 5 . + +. . . . . . . 6 7 +. 2 3 8 . 1 4 9 . +5 9 . . . . . . . + +. 4 9 2 1 . 5 . . +. . . . 5 . . 8 . +. . 8 3 . . . 4 . diff --git a/eureka.txt b/eureka.txt new file mode 100644 index 0000000..dc9e672 --- /dev/null +++ b/eureka.txt @@ -0,0 +1,19 @@ +. 1 E . . . . 5 . F 7 2 . . D +. . . A F . 7 . . . . C . 1 B +. 8 . . . . . . . 3 A E . . . + +D 4 7 F 1 . 9 A C . . . . . 3 +C 5 . 9 3 B . . . . . . F . . +. 6 . B . F 1 . . . 9 . D C 4 + +8 E B . 6 C . 3 . . . 9 4 F . +F 3 2 1 7 E B 9 . A C 6 8 D . +. . 9 . . 1 . 8 . 6 E 3 7 . . + +2 . 1 . . A . B D 5 . 7 . 9 C +B . 4 . D . . . . . . A . 5 6 +9 . . E A 4 . 2 . . . . 1 3 8 + +. B 3 7 . . 4 D . E . F . 2 1 +. 9 F . . . . C 8 . . . . . . +. . . 8 . . . . . . . . . 6 9 diff --git a/solve.cpp b/solve.cpp new file mode 100644 index 0000000..59c43e3 --- /dev/null +++ b/solve.cpp @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include +#include +#include + + +bool stdout_is_color_tty; + + +#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) + +#include +class Tty_init_static{ +public: + Tty_init_static(){ + stdout_is_color_tty=(bool)isatty(1); + } +} tty_init_static; + +#else + +class Tty_init_static{ +public: + Tty_init_static(){ + stdout_is_color_tty=false; + } +} tty_init_static; + +#endif + + +using namespace std; + + +string readfile(istream &is){ + string res; + char buf[1024]; + while(true){ + is.read(buf,sizeof(buf)); + int nread=is.gcount(); + if(nread==0)break; + res.append(buf,sizeof(buf)); + } + return res; +} + + +template +class Sudoku{ +private: + int bd[N][N]; // bd[y][x] + bitset poss[N][N]; + bool given[N][N]; + + void calcposs(){ + for(int y=0;y> &dst) const { + int miny=-1,minx=-1,mincount=N+1; + for(int y=0;y0&&count S(*this); + S.bd[miny][minx]=i; + S.solve(dst); + } + } + + bool solved() const { + if(!verifyConsistent())return false; + for(int y=0;y> &dst){ + do calcposs(); + while(resolveposs()); + if(solved()){ + dst.push_back(*this); + return; + } + recurseone(dst); + } + +public: + Sudoku(const string &init){ + static_assert(N>1&&BW>1&&BH>1&&BW*BH==N,"Box size inconsistent"); + + stringstream ss(init); + for(int y=0;y>c; + if(c=='.'){ + bd[y][x]=-1; + poss[y][x].set(); + given[y][x]=false; + continue; + } + int n=-1; + if(c>='1'&&c<='9')n=c-'0'; + else if(c>='A'&&c<='Z')n=c-'A'+10; + else if(c>='a'&&c<='z')n=c-'a'+10; + if(n<1||n>N)throw "Invalid character in init string for Sudoku"; + bd[y][x]=n; + poss[y][x].set(n-1); + given[y][x]=true; + } + } + } + + vector> solve(){ + vector> dst; + solve(dst); + return dst; + } + + bool verifyConsistent(bool diag=false) const { + for(int i=0;i seenH,seenV; + for(int j=0;j &sol) const { + for(int y=0;y + int compare(const Sudoku &other) const { + for(int y=0;yother.bd[y][x])return 1; + } + } + return 0; + } + + bool operator==(const Sudoku &other) const {return compare(other)==0;} + bool operator!=(const Sudoku &other) const {return compare(other)!=0;} + bool operator> (const Sudoku &other) const {return compare(other)> 0;} + bool operator>=(const Sudoku &other) const {return compare(other)>=0;} + bool operator< (const Sudoku &other) const {return compare(other)< 0;} + bool operator<=(const Sudoku &other) const {return compare(other)<=0;} + + template + friend ostream& operator<<(ostream &os,const Sudoku<_,BW_,BH_> &S); +}; + +template +ostream& operator<<(ostream &os,const Sudoku &S){ + for(int y=0;y0){ + if(y%BH==0)os<0){ + if(x%BW==0)os<<" "; + os<<' '; + } + bool color=stdout_is_color_tty&&!S.given[y][x]&&S.bd[y][x]!=-1; + if(color)os<<"\x1B[42;1m"; + if(S.bd[y][x]==-1)os<<'.'; + else if(S.bd[y][x]<=9)os< S(readfile(is)); + Sudoku origS(S); + + auto solutions=S.solve(); + if(solutions.size()==0){ + cerr<<"0 solutions :("<0&&sol==solutions[i-1])continue; + if(!first){ + cout<