Sudoku Funpark

Creating worlds most inefficient Sudoku solver, by trying every option, without any smart approach.

(This was a learning project to get a better grasp of Golang. But more important; It was fun to do!.)

Goals

  • Create the most inefficient Sudoku solver imaginable
  • Be a learning experience for the Go programming language

I wrote a blog post about this.

Features

  • Worlds least efficient Sudoku solver
  • Ability to assign a number of CPU cores to this task
  • Split workloads among several computers

Usage

To use the sudoku solver, run the binary with all the -row parameters available. Use other parameters to tune our output or CPU usage.

Usage of ./sudoku-funpark:
  -numcpu int
    	Number of CPU cores to assign to this task. (default 12)
  -output string
    	Type of output. 'human' for human readable. 'flat' for flat as stored in memory output. 'json' for JSON output. (default "human")
  -part int
    	Process part x in n parts. Cannot be lower than 1, or higher than specified in split. (default 1)
  -print string
    	'short': normal output;'long': normal output with timestamps; 'silent': Only print the results; (default "short")
  -row1 string
    	1st row of the sudoku puzzle. (default "000000000")
  -row2 string
    	2nd row of the sudoku puzzle. (default "000000000")
  -row3 string
    	4rd row of the sudoku puzzle. (default "000000000")
  -row4 string
    	4th row of the sudoku puzzle. (default "000000000")
  -row5 string
    	5th row of the sudoku puzzle. (default "000000000")
  -row6 string
    	6th row of the sudoku puzzle. (default "000000000")
  -row7 string
    	7th row of the sudoku puzzle. (default "000000000")
  -row8 string
    	8th row of the sudoku puzzle. (default "000000000")
  -row9 string
    	9th row of the sudoku puzzle. (default "000000000")
  -split int
    	Split the tasks in n parts. This depends on the availability of the first row. (default 1)

Instead of using the 3x3 blocks with 3x3 digits, it uses horizontal rows from top to bottom.

Example

To see the solver in action, run the tool with the following parameters.

For a short running (~14 seconds) example:

$ ./sudoku-funpark -row1 769104802 -row2 154800060 -row3 832700154 -row4 600900328 -row5 045328670 -row6 328670945 -row7 597410280 -row8 006283090 -row9 200590006

For a long running (~1 hours 15 minutes) example:

$ ./sudoku-funpark -row1 769104802 -row2 154800060 -row3 002700150 -row4 600900308 -row5 045328670 -row6 328670945 -row7 597410280 -row8 006283090 -row9 200590006

The outpot (of the short running parameters) will look something like this:

./sudoku-funpark -row1 769104802 -row2 154800060 -row3 832700154 -row4 600900328 -row5 045328670 -row6 328670945 -row7 597410280 -row8 006283090 -row9 200590006 
Loading blocks... Done! (38.957376ms)
Populating blocks... Done! (92.087174ms)
Number of (potential) solutions: 26542080
Validating solutions
Processing: 8% (2131893/26542080); Rate: 2131884/sec for 1.000028115s; Time left (est.): 11s
Processing: 16% (4292163/26542080); Rate: 2160219/sec for 1.000087826s; Time left (est.): 10s
Processing: 24% (6438334/26542080); Rate: 2146157/sec for 1.000017364s; Time left (est.): 9s
Processing: 32% (8529362/26542080); Rate: 2090965/sec for 1.000367121s; Time left (est.): 8s
Processing: 40% (10737065/26542080); Rate: 2207530/sec for 1.000072427s; Time left (est.): 7s
Processing: 48% (12958905/26542080); Rate: 2221755/sec for 1.000003187s; Time left (est.): 6s
Processing: 57% (15163877/26542080); Rate: 2204929/sec for 1.000002717s; Time left (est.): 5s
Processing: 65% (17254760/26542080); Rate: 2090742/sec for 1.00008452s; Time left (est.): 4s
Processing: 73% (19513142/26542080); Rate: 2258348/sec for 1.000071076s; Time left (est.): 3s
Processing: 82% (21795213/26542080); Rate: 2282028/sec for 1.000076024s; Time left (est.): 2s
Processing: 90% (24048891/26542080); Rate: 2253645/sec for 1.000146957s; Time left (est.): 1s
Processing: 98% (26226252/26542080); Rate: 2177215/sec for 1.000129955s; Time left (est.): 0s
Processing: 100% (26542080/26542080); Rate: 315792/sec for 1.000105149s; Time left (est.): 0s
Validated solutions (13.001683829s)

Solution #1:
╔═══════════╗
║769│154│832╢
║154│832│769╢
║832│769│154╢
╟───┼───┼───╢
║671│945│328╢
║945│328│671╢
║328│671│945╢
╟───┼───┼───╢
║597│416│283╢
║416│283│597╢
║283│597│416╢
╚═══════════╝

Caveats

While this may very well solve all possible Sudoku puzzles (including the one designed against brute force algorithms), the blanks in the puzzle, the harder it is, the more possible solutions there are, the more solutions it needs to parse, the longer it takes. As this is a computational heavy program, the more CPU you throw against it the faster it will solve issues.

Generating your own blocks

To generate your own blocks, you could use the following code:

func (solver *Solver) generate_blocks() []int {

	var blocks []int
	decvals := [9]int{49, 50, 51, 52, 53, 54, 55, 56, 57}

	for counter := 123456789; counter <= 987654321; counter++ {

		// Convert number to string ([]byte)
		digits := strconv.Itoa(counter)

		// Check if every number is only represented only once
		var valid bool
		valid = true
		for decval := range decvals {
			var count int
			for digit := range digits {
				if digits[digit] == byte(decvals[decval]) {
					count = count + 1
				}
			}

			if count != 1 {
				valid = false
			}
		}

		if valid {
			blocks = append(blocks, counter)
		}
	}

	return blocks

}
Description
Creating worlds most inefficient Sudoku solver, by trying every option, without any smart approach. (This was a learning project to get a better grasp of Golang. And more important; It was fun to do!).
Readme 1.3 MiB
2025-01-28 21:28:33 +01:00
Languages
Go 100%