--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gotak/gotak.go Fri Sep 02 21:50:48 2016 +0200
@@ -0,0 +1,208 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "time"
+
+ flag "github.com/docker/docker/pkg/mflag"
+
+ "mikael/takuzu"
+)
+
+var verbosity int
+
+func newTakuzuGameBoard(size int, simple bool, jobs int, buildBoardTimeout, reduceBoardTimeout time.Duration, minRatio, maxRatio int) *takuzu.Takuzu {
+ results := make(chan *takuzu.Takuzu)
+
+ newTak := func(i int) {
+ takuzu, err := takuzu.NewRandomTakuzu(size, simple, fmt.Sprintf("%v", i),
+ buildBoardTimeout, reduceBoardTimeout, minRatio, maxRatio)
+
+ if err == nil && takuzu != nil {
+ results <- takuzu
+ if verbosity > 0 && jobs > 1 {
+ log.Printf("Worker #%d done.", i)
+ }
+ } else {
+ results <- nil
+ }
+ }
+
+ if jobs == 0 {
+ return nil
+ }
+ for i := 0; i < jobs; i++ {
+ go newTak(i)
+ }
+ tak := <-results
+ return tak
+}
+
+func main() {
+ var game string
+
+ vbl := flag.Uint([]string{"-vl"}, 0, "Verbosity Level")
+ simple := flag.Bool([]string{"-simple"}, false, "Only look for trivial solutions")
+ out := flag.Bool([]string{"-out"}, false, "Send solution string to output")
+ flag.StringVar(&game, []string{"-game"}, "", "Load game string")
+ schrodLvl := flag.Uint([]string{"-x-sl"}, 0, "[Advanced] Schrödinger level")
+ resolveTimeout := flag.Duration([]string{"-x-timeout"}, 0, "[Advanced] Resolution timeout")
+ buildBoardTimeout := flag.Duration([]string{"-x-build-timeout"}, 5*time.Minute, "[Advanced] Build timeout per resolution")
+ reduceBoardTimeout := flag.Duration([]string{"-x-reduce-timeout"}, 20*time.Minute, "[Advanced] Reduction timeout")
+ buildMinRatio := flag.Uint([]string{"-x-new-min-ratio"}, 55, "[Advanced] Build empty cell ratio (40-60)")
+ buildMaxRatio := flag.Uint([]string{"-x-new-max-ratio"}, 62, "[Advanced] Build empty cell ratio (50-99)")
+ all := flag.Bool([]string{"-all"}, false, "Look for all possible solutions")
+ reduce := flag.Bool([]string{"-reduce"}, false, "Try to reduce the number of digits")
+ buildNewSize := flag.Uint([]string{"-new"}, 0, "Build a new takuzu board (with given size)")
+ pdfFileName := flag.String([]string{"-to-pdf"}, "", "PDF output file name")
+ workers := flag.Uint([]string{"-workers"}, 1, "Number of parallel workers (use with --new)")
+
+ flag.Parse()
+
+ verbosity = int(*vbl)
+ takuzu.SetVerbosityLevel(verbosity)
+ takuzu.SetSchrodingerLevel(*schrodLvl)
+
+ var tak *takuzu.Takuzu
+
+ if game != "" {
+ var err error
+ tak, err = takuzu.NewFromString(game)
+ if tak == nil || err != nil {
+ fmt.Fprintln(os.Stderr, "Error:", err)
+ tak = nil
+ }
+ }
+
+ if *buildNewSize > 0 {
+ if verbosity > 1 {
+ log.Printf("buildBoardTimeout: %v", *buildBoardTimeout)
+ log.Printf("reduceBoardTimeout: %v", *reduceBoardTimeout)
+ log.Printf("Free cell min ratio: %v", *buildMinRatio)
+ log.Printf("Free cell max ratio: %v", *buildMaxRatio)
+ }
+ tak = newTakuzuGameBoard(int(*buildNewSize), *simple,
+ int(*workers),
+ *buildBoardTimeout, *reduceBoardTimeout,
+ int(*buildMinRatio), int(*buildMaxRatio))
+ }
+
+ if tak == nil {
+ fmt.Fprintln(os.Stderr, "Could not create takuzu board.")
+ os.Exit(255)
+ }
+
+ tak.DumpBoard()
+ fmt.Println()
+
+ if *pdfFileName != "" {
+ if err := tak2pdf(tak, *pdfFileName); err != nil {
+ log.Println(err)
+ os.Exit(1)
+ }
+ if *out {
+ tak.DumpString()
+ }
+ os.Exit(0)
+ }
+
+ if *buildNewSize > 0 {
+ if *out {
+ tak.DumpString()
+ }
+ os.Exit(0)
+ }
+
+ if *reduce {
+ if verbosity > 1 {
+ log.Printf("buildBoardTimeout: %v", *buildBoardTimeout)
+ log.Printf("reduceBoardTimeout: %v", *reduceBoardTimeout)
+ }
+ var err error
+ if tak, err = tak.ReduceBoard(*simple, "0", *buildBoardTimeout, *reduceBoardTimeout); err != nil {
+ log.Println(err)
+ os.Exit(1)
+ }
+
+ tak.DumpBoard()
+ fmt.Println()
+
+ if *out {
+ tak.DumpString()
+ }
+
+ os.Exit(0)
+ }
+
+ if *simple {
+ full, err := tak.TrySolveTrivial()
+ if err != nil {
+ log.Println(err)
+ os.Exit(1)
+ }
+ if !full {
+ tak.DumpBoard()
+ log.Println("The takuzu could not be completed using trivial methods.")
+ os.Exit(2)
+ }
+
+ log.Println("The takuzu is correct and complete.")
+ tak.DumpBoard()
+ fmt.Println()
+
+ if *out {
+ tak.DumpString()
+ }
+ os.Exit(0)
+ }
+
+ var allSol *[]takuzu.Takuzu
+ if *all {
+ allSol = &[]takuzu.Takuzu{}
+ }
+ res, err := tak.TrySolveRecurse(allSol, *resolveTimeout)
+ if err != nil && verbosity > 1 {
+ // The last trivial resolution failed
+ log.Println("Trivial resolution failed:", err)
+ }
+
+ // Ignoring res & err if a full search was requested
+ if *all {
+ log.Println(len(*allSol), "solution(s) found.")
+ if len(*allSol) > 0 {
+ for _, s := range *allSol {
+ if *out {
+ s.DumpString()
+ } else {
+ s.DumpBoard()
+ fmt.Println()
+ }
+ }
+ if len(*allSol) > 1 {
+ os.Exit(3)
+ }
+ os.Exit(0)
+ }
+ fmt.Println("No solution found.")
+ os.Exit(2)
+ }
+
+ if err != nil {
+ log.Println(err)
+ os.Exit(1)
+ }
+ if res != nil {
+ res.DumpBoard()
+ fmt.Println()
+
+ if *out {
+ res.DumpString()
+ }
+ os.Exit(0)
+ }
+
+ fmt.Println("No solution found.")
+ os.Exit(2)
+}