Implement a Non-Guessing Sudoku Solver

27

5

Implement the shortest Sudoku solver.

Sudoku Puzzle:

 | 1 2 3 | 4 5 6 | 7 8 9
-+-----------------------
A|   3   |     1 |
B|     6 |       |   5
C| 5     |       | 9 8 3
-+-----------------------
D|   8   |     6 | 3   2
E|       |   5   |
F| 9   3 | 8     |   6
-+-----------------------
G| 7 1 4 |       |     9
H|   2   |       | 8
I|       | 4     |   3

Answer:

 | 1 2 3 | 4 5 6 | 7 8 9
-+-----------------------
A| 8 3 2 | 5 9 1 | 6 7 4
B| 4 9 6 | 3 8 7 | 2 5 1
C| 5 7 1 | 2 6 4 | 9 8 3
-+-----------------------
D| 1 8 5 | 7 4 6 | 3 9 2
E| 2 6 7 | 9 5 3 | 4 1 8
F| 9 4 3 | 8 1 2 | 7 6 5
-+-----------------------
G| 7 1 4 | 6 3 8 | 5 2 9
H| 3 2 9 | 1 7 5 | 8 4 6
I| 6 5 8 | 4 2 9 | 1 3 7

Rules:

  1. Assume all mazes are solvable by logic only.
  2. All input will be 81 characters long. Missing characters will be 0.
  3. Output the solution as a single string.
  4. The "grid" may be stored internally however you wish.
  5. The solution must use a non-guessing solution. (see Sudoku Solver)

Example I/O:

>sudoku.py "030001000006000050500000983080006302000050000903800060714000009020000800000400030"
832591674496387251571264983185746392267953418943812765714638529329175846658429137

snmcdonald

Posted 2011-02-01T23:41:33.200

Reputation: 641

@Jonathan, IMO the main point to solving it logically is to estimate the difficulty. – Peter Taylor – 2011-02-08T16:45:24.890

4Problems "solvable by logic only" is very vague. Do you mean, perhaps, using only the basic steps of a) Writing a value in a cell for which it's value not in its row, column, and block b) Identifying a number that can only go in one place in its row, column, or block, and writing it there? – xnor – 2014-05-17T02:41:17.493

You should really add a time limit. – JPvdMerwe – 2011-02-02T00:30:24.037

Pretty sure this has been done before. There are some very short solvers out there, but some puzzles will take a long long time to solve using a naive algorithm – gnibbler – 2011-02-02T00:40:40.407

1@JPvdMerwe: Good point, but a time limit would be hard to standardize. – snmcdonald – 2011-02-02T01:19:44.070

1@gnibbler: It might have been done before (but not on codegolf.se). I think it will still be fun to solve as well as add some value to the community, especially if one goes about it honestly. – snmcdonald – 2011-02-02T01:47:56.550

2I like this one. I've been hesitant to try an actual golf solution, and I've been thinking about writing a Sudoku solver (it seems like a fun exercise). I think it's something people like me, who've never golfed before, could use as a jumping-off point. And once I come up with one, I might then golf it. – Andy – 2011-02-02T04:47:18.203

@Andy: gnibbler and JPvdMerwe brought up a good point that naive solvers could eventually solve this questions given enough time. My intention for this question was for it be solved specifically by logic. Since no one has answered I think I will add that specification. – snmcdonald – 2011-02-02T04:51:02.487

@snmcdonald: Pardon my ignorance, but what exactly do you mean by "by logic"? Do you mean, no brute-forcing? – Andy – 2011-02-02T04:55:06.147

@Andy: see http://www.sudokusolver.co.uk/step.html

– snmcdonald – 2011-02-02T04:56:30.730

is bruteforce guessing? – st0le – 2011-02-02T11:36:18.287

@stole: yes it is. We could have another Code Golf that is a guessing only solution. As JPvdMerwe suggested it might be a good idea to add a time limit to a guessing solution. – snmcdonald – 2011-02-02T14:57:15.597

You could make use of answers here: http://projecteuler.net/index.php?section=problems&id=96

– Nick T – 2011-02-03T03:06:57.787

This is definitely an interesting problem. Unfortunately, since it's a lot harder than brute-forcing it, and brute-forcing it appears to be quite fast ( http://codegolf.stackexchange.com/questions/378/implement-a-brute-force-sudoku-solver ), I'm not sure that there's much point in solving it logically other than the challenge. If all you care about is solving it, then brute force does just fine (and it's a lot easier to write). Nonetheless, solving it logically is definitely a great challenge.

– Jonathan M Davis – 2011-02-03T08:31:59.913

Answers

4

RUBY (449 436 chars)

I=*(0..8)
b=$*[0].split('').map{|v|v<'1'?I.map{|d|d+1}:[v.to_i]};f=b.map{|c|!c[1]}
[[z=I.map{|v|v%3+v/3*9},z.map{|v|v*3}],[x=I.map{|v|v*9},I],[I,x]
].map{|s,t|t.map{|i|d=[a=0]*10;s.map{|j|c=b[i+j];c.map{|v|d[v]+=1if !f[i+j]}
v,r=*c;s.map{|k|b[i+k].delete(v)if j!=k}if !r 
s[(a+=1)..8].map{|k|s.map{|l|b[i+l]-=c if l!=k&&l!=j}if c.size==2&&c==b[i+k]}}
v=d.index 1;f[i+k=s.find{|j|b[i+j].index v}]=b[i+k]=[v]if v}}while f.index(!1)
p b*''

Example:

C:\golf>soduku2.rb 030001000006000050500000983080006302000050000903800060714000009020000800000400030
"832591674496387251571264983185746392267953418943812765714638529329175846658429137"

quick explanation:
Board b is an array of 81 arrays holding all the possible values for each cell. The array on line three holds [offset,start_index] for each group (boxes,rows,columns). Three tasks are performed while iterating through the groups.

  1. The value of any cell of size 1 is removed from the rest of the group.
  2. If any pair of cells contain the same 2 values, these values are removed from the rest of the group.
  3. The count of each value is stored in d - if there is only 1 instance of a value, we set the containing cell to that value, and mark the cell fixed in f

Repeat until all cells are fixed.

AShelly

Posted 2011-02-01T23:41:33.200

Reputation: 4 281

You can omit the brackets in I=*(0..8), will save 2 chars. – Wile E. Coyote – 2011-02-08T17:02:08.463

I get sudokusolver.rb:8: unterminated string meets end of file if I start it with ruby1.8 sudokusolver.rb 030.... What am I doing wrong? – user unknown – 2011-05-04T23:53:41.343

Looks like there is an extra ' on the last line. Not sure how that got there... – AShelly – 2011-05-05T02:27:11.367

2

Prolog - 493 Characters

:-use_module(library(clpfd)).
a(X):-all_distinct(X).
b([],[],[]).
b([A,B,C|X],[D,E,F|Y],[G,H,I|Z]):-a([A,B,C,D,E,F,G,H,I]),b(X,Y,Z).
c([A,B,C,D,E,F,G,H,I|X])-->[[A,B,C,D,E,F,G,H,I]],c(X).
c([])-->[].
l(X,Y):-length(X,Y).
m(X,Y):-maplist(X,Y).
n(L,M):-l(M,L).
o(48,_).
o(I,O):-O is I-48.
:-l(L,81),see(user),m(get,L),seen,maplist(o,L,M),phrase(c(M),R),l(R,9),m(n(9),R),append(R,V),V ins 1..9,m(a,R),transpose(R,X),m(a,X),R=[A,B,C,D,E,F,G,H,I],b(A,B,C),b(D,E,F),b(G,H,I),flatten(R,O),m(write,O).

Output:

Inputting: 000000000000003085001020000000507000004000100090000000500000073002010000000040009 Outputs: 987654321246173985351928746128537694634892157795461832519286473472319568863745219

Inputting: 030001000006000050500000983080006302000050000903800060714000009020000800000400030 Outputs: 832591674496387251571264983185746392267953418943812765714638529329175846658429137

MT0

Posted 2011-02-01T23:41:33.200

Reputation: 3 373