Sudoku Programmers Forum Index

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister   ProfileProfile   Log inLog in          Games  Calendar

Log in to check your private messagesLog in to check your private messages   

Four line sudoku solver

 
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Programming sudoku
View previous topic :: View next topic  
Author Message
rwaddilove

Joined: 17 Mar 2006
Posts: 5
:

Items
PostPosted: Fri Mar 17, 2006 12:02 pm    Post subject: Four line sudoku solver Reply with quote

Sudoku puzzles can be solved with just 4 lines of code. Here's it is:

1 sp(cell(ptr))=(sp(cell(ptr)) + 1) mod 10
2 if sp(cell(ptr))=0 then ptr=ptr+1:goto 1
3 if countnum(cell(ptr))=3 then ptr=ptr-1
4 if ptr>-1 then goto 1

Of course, it needs a bit of explanation. This is a brute force method, but it is so short and simple that it is very fast. You need to create two arrays and a pointer like this:

sp(80) is the sudoku puzzle - 9 x 9 grid, 81 cells, numbered 0-80
cell(80) is a list of blank cells - when you read in the puzzle, store the blank cell numbers here
ptr=points to the last blank cell in the list

One other thing you need is a countnum() function. This counts how many times a number appears. It should appear once in a row, once in a column and once in a block, hence the if countnum()=3 then...

That's it. You want to see some real code? Here it is in Visual Basic - I dislike goto so the structured version is a little longer:
Code:

While ptr > -1
  sp(cell(ptr)) = (sp(cell(ptr)) + 1) Mod 10
  If sp(cell(ptr)) = 0 Then
    ptr = ptr + 1
  Else
    If CountNum(cell(ptr)) = 3 Then ptr = ptr - 1
  End If
Wend

That's the main program loop that solves the puzzle in sp() - just print out the array afterwards to see the solution. The CountNum() function just counts the occurances like this:
Code:

Function CountNum(ByVal n As Integer) As Integer
Dim i, j, k, r, c As Integer

k = 0   'count

'check the row and column
r = n \ 9   'row 0-8
c = n Mod 9   'column 0-8
For i = 0 To 8
  If sp(r * 9 + i) = sp(n) Then k = k + 1   'row
  If sp(c + i * 9) = sp(n) Then k = k + 1   'column
Next

'check the block
c = 3 * (c \ 3)   'left column of block 0/3/6
r = 3 * (r \ 3)    'top row of block 0/3/6
For i = 0 To 2
  For j = c To c + 2
    If sp((r + i) * 9 + j) = sp(n) Then k = k + 1
  Next
Next
CountNum = k

End Function

This function could be made faster by checking the row and exiting if there's more than one, then checking the column and exiting if more than one, then checking the block. It would save some checking. However, it seems fast enough as it is. VB isn't particularly quick, but simple puzzles are solved instantaneously and the hard ones only take 5 or 10 seconds.
Back to top
View user's profile Send private message Visit poster's website
rwaddilove

Joined: 17 Mar 2006
Posts: 5
:

Items
PostPosted: Sun Mar 19, 2006 9:34 am    Post subject: The difference a compiler makes... Reply with quote

I tracked down the hardest puzzle I could find on this board and ran it through the Visual Basic program above. It took about 40 seconds to solve. Removing the For...Next loops in the CountNum function and writing out the code in full reduced this to 9 seconds, which is quite a saving.

However, seeing other people talking of solving puzzles in milliseconds left me slightly disappinted to say the least.

I copied the code from VB and pasted it into Blitz Basic. Hardly any changes were required to get it working and when I ran the same puzzle, it was solved in around 700 milliseconds. It just shows what a difference the compiler makes.

I wonder if C would be even faster?

Can anyone write in assembly language these days? Presumably this would be the ultimate, but I've not done this since the days when everything was Z80 or 6502 powered.
Back to top
View user's profile Send private message Visit poster's website
tarek

Joined: 31 Dec 2005
Posts: 153
:
Location: London, UK

Items
PostPosted: Sun Mar 19, 2006 11:33 am    Post subject: Reply with quote

I actually had one of those,

It was revolutinary in its time as it had a whole 1KB of memory....which then can be expanded to a " 16 KB " memory, I wouldn't have thought that it would withstand DLX or even brute force to be honest Very Happy

Tarek
Back to top
View user's profile Send private message
rwaddilove

Joined: 17 Mar 2006
Posts: 5
:

Items
PostPosted: Sun Mar 19, 2006 1:30 pm    Post subject: Down memory lane Reply with quote

You're thinking of the ZX-81, I think. I was just talking about the Z80 processor in general, which was used in several different computers. You could quite easily write a soduku solver for the ZX-81 because it requires very little memory and only about 20 or 30 lines of Basic. Mind you, it would take about 3 days to come up with a solution! Anyone want to try this with a ZX-81 emulator?
Back to top
View user's profile Send private message Visit poster's website
LangPol

Joined: 20 Mar 2006
Posts: 6
:

Items
PostPosted: Mon Mar 20, 2006 2:18 pm    Post subject: Re: Four line sudoku solver Reply with quote

Never, ever, throw out something like that. It sounds like a challenge.

Here's a Perl version, not mine, andall you need is the array A:

use integer;@A=split//,<>;sub R{for$i(0..80){next if$A[$i];my%t=map{$_/9
==$i/9||$_%9==$i%9||$_/27==$i/27&&$_%9/3==$i%9/3?$A[$_]:0=>1}0..80;R($A[
$i]=$_)for grep{!$t{$_}}1..9;return$A[$i]=0}die@A}R

3 lines.
Back to top
View user's profile Send private message
foxglove

Joined: 04 Feb 2006
Posts: 42
:
Location: Portugal

Items
PostPosted: Mon Mar 27, 2006 6:34 pm    Post subject: Re: Four line sudoku solver Reply with quote

rwaddilove wrote:
Sudoku puzzles can be solved with just 4 lines of code.


You are right, but...

Here is a very fast to solve:

Code:

9   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .
.   .   .   .   .   .   .   .   .


and here one that takes a looong time to solve:

Code:

4   .   7   9   .   .   .   .   3
.   1   2   .   6   .   5   7   9
.   .   .   .   .   .   .   8   .
.   .   .   .   .   7   .   .   .
3   5   .   .   8   .   .   6   7
.   .   .   5   .   .   .   .   .
.   9   .   .   .   .   .   .   .
6   8   4   .   9   .   .   3   .
2   .   .   .   .   3   6   .   4


so, to be really right, you should say: proper Sudoku puzzles can be solved with just 4 lines of code.
Back to top
View user's profile Send private message Visit poster's website
elroy

Joined: 16 Mar 2006
Posts: 6
:

Items
PostPosted: Sat Apr 01, 2006 7:19 pm    Post subject: Reply with quote

rwaddilove fm elroy:
Even in VB, your cute algorithm can be speeded 60 times faster * - and be smaller - if done in the "quise" of machine-language & bit-manipulation as you inclined:
Your complete VB routine, for example, could evolve to following, requiring just initial setup of its arrays (for which, further below at bottom, an illustrative example/working macro [Excel] is also submitted)
Code:
Sub SolveIt(S%(),L%(),p%,rq%(),cq%(),bq%(),M%()):  Dim r%,c%,b%,t%,u%,q%
While p > 0: r = L(p, 0): c = L(p, 1): b = L(p, 2): t = S(r, c)  '<cell info
  u = t: q = rq(r) Or cq(c) Or bq(b): DO: If u = 0 Then u = 1 Else u = u + u
         Loop While u And q: If u > 256 Then u = 0: p = p + 1 Else p = p - 1
  S(r, c) = u      '<update cell (S) to new value, also update the 3 queues>
  t = (u - t):  rq(r) = rq(r) + t:  cq(c) = cq(c) + t:  bq(b) = bq(b) + t
Wend: End Sub 'puzzle completely solved             'notes: M not used here
Cells/Queues: Cell-vals (1-9) are stored as unique bit in 9-bit word (ie, 8 = b8, w/ only 1 bit "on" at any time), whereas a candidate Queue, in essence, is an "extra" cell for each row/col and box but with any combination of its 9 bits "on" any time, representing all current cell-values in that row/col/box: In above, the (nine) "row" queues for example are the array rq().. The target-cell value is "incremented" (by doubling) until a "hole" is found in combined bit-mask of the three applicable queues or until so forced from 9 to 0 (no bit on).
Even faster (130%) is the following:
Code:
Sub SolveIt(S%(), L%(), p%,rq%(),cq%(),bq%(),M%()) :Dim r%,c%,b%,t%,u%,q%
While p > 0: r = L(p, 0): c = L(p, 1): b = L(p, 2): t = S(r, c) '<cell info
 q = t + t + (t > 0) Or rq(r) Or cq(c) Or bq(b)            '<candidate mask
 u = M(q, 0): p = p + M(q, 1): S(r, c) = u:  '<lookup new val & pointer dir
 t = (u - t):  rq(r) = rq(r) + t:  cq(c) = cq(c) + t:  bq(b) = bq(b) + t
Wend: End Sub 'puzzle solved. '(notes: true=(-1); t+t-1 = t +any lower bits)
Here M is lookup table of pre-calc'd candidate-solution/pointer-control (analogous to rom-mapped processing) which eliminates serial incrementing (table-generator is included in same import/export-macro (Excel) below); Yes, expression "t+t+(t>0)" in above could also be similarly pre-mapped (function of t) but buys no VB speed.
<>
** And I know as you know, an important speed-player (factor of 3) in high-level like VB is that all possible variables/arrays in highly-repetitive routines are assuredly/PROPERLY declared As Integer (or %).. so perhaps maybe the above isn't really 60 times faster but only 21 times or so - just meant to draw some important attention to that -- and now here's example Excel-based puzzle import/exporter (host program):
Code:
Sub MacroImportExportPuzzleFmToWorksheet()  '(1st nine rows/cols of wksht):
Dim S%(8, 8), L%(81, 3), rq%(8), cq%(8), bq%(8), p%, r%, c%, b%, t, x%, y%
Dim M%(511, 1) 'make table(for wherever used): candidate & pointer resolver
 For y = 0 To 511: x = 1:  While x And y: x = x + x: Wend:  x = x And 511 _
 : M%(y, 0) = x: M%(y, 1) = 1 + 2 * (x > 0): Next     '(true = -1 in basic)
For Each t In [A1:I9]  'make list L = row/col/box of each (0)cell(target t)
  r = t.Row - 1:  c = t.Column - 1:  b = (r \ 3) * 3 + c \ 3   'b =box# 0-8
  If t = 0 Then x = 0: p = p + 1: L(p, 0) = r: L(p, 1) = c: L(p, 2) = b _
           Else x = 2 ^ (t - 1)      '(x = t as a mapped binary-bit (b1-b9)
  S(r, c) = x: rq(r) = rq(r) Or x: cq(c) = cq(c) Or x: bq(b) = bq(b) Or x
Next: Call SolveIt(S, L, p, rq, cq, bq, M)         '<GO SOLVE WHOLE PUZZLE
For Each t In [A1:I9]: Let x = S(t.Row - 1, t.Column - 1): Let y = 10
  While (x > 0): x = x + x And 511: y = y - 1: Wend: t.Value = y 'send it
Next: End Sub  '(S=puzzle; rq/cq/bq = canditate-queue for each row/col/box)
NOTE: Worksheet-cells in Excel (especially if originally imported to wksht as text) stubbornly aren't always recognized numeric even if one tries to reformat them, test by seeing if they can be made to show a decimal format.
<>
Your basic simple algorthm is a handy speedy no-nonsense little guy - can also check unigueness/validity, etc, easily imbedded in any higher host analytic-program. Thanks for sharing it.
I wonder what your Blitz Basic could further make of this?

Elroy


Last edited by elroy on Sun Apr 02, 2006 4:55 am; edited 8 times in total
Back to top
View user's profile Send private message
elroy

Joined: 16 Mar 2006
Posts: 6
:

Items
PostPosted: Sat Apr 01, 2006 7:40 pm    Post subject: Reply with quote

BTW here's a good valid test-puzzle - Vidarino's old "Monster #2:
Code:
 |8..|4..|6..|
 |.3.|.6.|.7.|
 |..7|...|..2|
 |---+---+---|
 |1..|6..|3..|
 |.7.|.4.|.8.|
 |..3|..9|..6|
 |---+---+---|
 |...|8..|4..|
 |.9.|.5.|.2.|
 |..1|...|..5|
elroy
Back to top
View user's profile Send private message
Agent Allen

Joined: 01 Oct 2005
Posts: 34
:

Items
PostPosted: Sun Apr 02, 2006 9:00 pm    Post subject: Re: Four line sudoku solver Reply with quote

LangPol wrote:
Never, ever, throw out something like that. It sounds like a challenge.


Emulator, pah! Surely someone has got a ZX81 under their bed they can blow the dust off?

You should find it under your Adam and the Ants T-Shirt and next to your Starsky & Hutch toy car!

Alternatively, I see ZX81's fetch about £30.00 on eBay.
They cost about £70.00 originally!
Not a collectors item just yet...

Go on someone...
_________________
Agent A
Back to top
View user's profile Send private message
docnzok

Joined: 10 Apr 2006
Posts: 1
:

Items
PostPosted: Mon Apr 10, 2006 8:34 pm    Post subject: Testing your theory Reply with quote

Hey,

I am trying to test your code in VB, but am having trouble accessing the array member that is stored with the pointer.

Can you send me the code that you used to declare the pointer and then how you access that memory location.

I am in sync with everything else you are doing.

Thanks

I declare the pointer like this.
Dim ptr As Long

The set it like this
ptr = VarPtr(cell(x))

I get a memory address correctly using this technique but when I try to reference the ptr using your code:
sp(cell(ptr))
I get out of range because the memory address is way higher than the original cell(80) declaration.

Thanks
Back to top
View user's profile Send private message
Germanboy

Joined: 10 May 2006
Posts: 1
:

Items
PostPosted: Wed May 10, 2006 11:29 am    Post subject: complete source code Reply with quote

who can send me the complete source code (all parts zipped)? iI cannot understand the whole code from rwaddilove!

Thanks

Germanboy
Back to top
View user's profile Send private message Send e-mail
Lunatic

Joined: 11 Mar 2007
Posts: 166
:
Location: Ghent - Belgium

Items
PostPosted: Wed Mar 14, 2007 10:24 pm    Post subject: Reply with quote

I've put a small VB6 program on my website to test any sudoku if it has one, more then one or no solution at all. The program is based on the code from rwaddilove.
Since this is my first posting in this forum, I'm not allowed to post any URL, so contact me if you want me to send the zipped source code.
Greetz,
Lunatic Wink
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Pat

Joined: 06 Sep 2006
Posts: 128
:

Items
PostPosted: Fri Mar 16, 2007 9:48 am    Post subject: re: Website Reply with quote

Lunatic wrote:

Since this is my first posting in this forum, I'm not allowed to post any URL


        but you are allowed to indicate the URL of your Website --
        in your Profile !
Back to top
View user's profile Send private message Visit poster's website
Lunatic

Joined: 11 Mar 2007
Posts: 166
:
Location: Ghent - Belgium

Items
PostPosted: Thu Mar 22, 2007 11:28 pm    Post subject: Reply with quote

Ok, I have rearranged my website so that the zipped file of the sudoku test can be downloaded easely.
I also added my website's url at my profile. Choose "English" and then "Sudoku". You'll find a screenshot of the little program and a link to download.
I've included some basic solving techniques in the sudoku uniqueness tester, to assist solving (pre-solve) before the brute force solving. There's an evil sudoku in .txt format in the zipped file (to be dragged 'n' dropped). There are some additional lines added at the brute force routines, so one can see the brute force at work on screen, but this will slow down the proces. You can even dowload my own sudoku programm 'MPQ Sudoku' from my website.

Have fun.
_________________
Marc
~~~<><~~~<><~~~<><~~~<><~~~
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Programming sudoku All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Sudoku Programmers topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group

Igloo Theme Version 1.0 :: Created By: Andrew Charron