Fast sudoku solver
Monkey Forums/Monkey Programming/Fast sudoku solver
| ||
strict global start:Int[]= [ 0,308,0, 75,0,180, 2,10,400, 510,30,96, 0,0,0, 640,90,18, 8,60,900, 91,0,670, 0,905,0 ] Global indexes:Int[]= [ 0,9,18,0,10,18,0,11,18, 0,12,19,0,13,19,0,14,19, 0,15,20,0,16,20,0,17,20, 1,9,18,1,10,18,1,11,18, 1,12,19,1,13,19,1,14,19, 1,15,20,1,16,20,1,17,20, 2,9,18,2,10,18,2,11,18, 2,12,19,2,13,19,2,14,19, 2,15,20,2,16,20,2,17,20, 3,9,21,3,10,21,3,11,21, 3,12,22,3,13,22,3,14,22, 3,15,23,3,16,23,3,17,23, 4,9,21,4,10,21,4,11,21, 4,12,22,4,13,22,4,14,22, 4,15,23,4,16,23,4,17,23, 5,9,21,5,10,21,5,11,21, 5,12,22,5,13,22,5,14,22, 5,15,23,5,16,23,5,17,23, 6,9,24,6,10,24,6,11,24, 6,12,25,6,13,25,6,14,25, 6,15,26,6,16,26,6,17,26, 7,9,24,7,10,24,7,11,24, 7,12,25,7,13,25,7,14,25, 7,15,26,7,16,26,7,17,26, 8,9,24,8,10,24,8,11,24, 8,12,25,8,13,25,8,14,25, 8,15,26,8,16,26,8,17,26 ] Global Number_of_bits:Int[]=[ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8, 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9] Global Highest_bitnumber:Int[]=[ ' Return highest bitnumber + 1 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9] Class Myerr Extends Throwable Field msg:string Method New(s:String) msg=s End method End class Class sudoku Const RASTERSIZE:=81 Const FREESIZE:=27 Field raster:Int[RASTERSIZE] Field free:Int[FREESIZE] Field stack:Int[RASTERSIZE] Field sp:int Field i0:Int,i1:Int,i2:Int Field freebits:Int Field solutioncnt:int Method reset_all_free:Void() For Local i:Int=0 Until FREESIZE free[i]=$1ff Next End Method init_stack:Void() sp=0 For Local i:Int=0 Until RASTERSIZE If raster[i]=0 stack[sp]=i sp+=1 end end End Method init:Void(startraster:Int[]) If startraster.Length<>FREESIZE Throw New Myerr("Startraster length not 27 !!") Local t:Int,z:Int,i:Int,x:Int solutioncnt=0 sp=0 reset_all_free For i=0 Until RASTERSIZE raster[i]=0 next x=RASTERSIZE-1 For i=FREESIZE-1 To 0 Step -1 z=startraster[i] For Local j:Int=1 To 3 t=z Mod 10 If t<>0 set_occupied x,(1 Shl (t-1)) z/=10 x-=1 next Next init_stack end Method New(is:Int[]) init is End Method Method showraster:Void() Local n:Int=0,v:Int=0,n2:Int=0,n3:Int=0 Local s:String="" For Local i:Int=0 Until RASTERSIZE v=v*10+Highest_bitnumber[raster[i]] n+=1 If n=3 If s="" s+=v Else s+=("|"+v) n=0 v=0 n2+=1 Endif If n2=3 Print(s) s="" n2=0 n3+=1 If n3=3 And i<>(RASTERSIZE-1) n3=0 Print("---+---+---") end next End Method Method set_indexes:Void(pos:Int) pos=(pos Shl 1) + pos 'pos*=3 i0=indexes[pos+0] i1=indexes[pos+1] i2=indexes[pos+2] End Method get_free:void(pos:Int) set_indexes pos freebits=free[i0] & free[i1] & free[i2] End Method set_free:Void(pos:Int) ' n goes from 1 to 9 Local n:Int=raster[pos] If n=0 return raster[pos]=0 set_indexes pos free[i0]|=n free[i1]|=n free[i2]|=n End Method set_occupied:Void(pos:Int,n:Int) set_indexes pos raster[pos]=n free[i0]~=n free[i1]~=n free[i2]~=n End Method find_best_pos:Int() Local n:Int,oldn:Int=9,newpos:Int=RASTERSIZE,pos:Int,i:Int,x:Int=-1 Local fb:Int=0 i=sp-1 While i>=0 pos=stack[i] get_free(pos) n=Number_of_bits[freebits] If n=0 Return -1 If n=1 newpos=pos x=i Exit end If n<oldn oldn=n newpos=pos fb=freebits x=i End i-=1 End sp-=1 stack[x]=stack[sp] If n>1 freebits=fb Return newpos End Method solveloop:Void() If sp=0 If solutioncnt=0 showraster solutioncnt+=1 Else Throw New Myerr("Aborted. More then 1 solution !!") end Return end Local pos:Int,bm:Int,t:Int pos=find_best_pos() If pos<0 Return bm=freebits While bm t=1 Shl (Highest_bitnumber[bm]-1) set_occupied pos,t solveloop set_free pos bm~=t Wend stack[sp]=pos sp+=1 end Method solve:Void() init start Print "" solveloop If solutioncnt=0 Throw New Myerr("No solution found !!") End End Class Function Main:Int() Try Local s:sudoku= New sudoku(start) s.solve Catch ex:Myerr Print ex.msg End Return 0 End function |
| ||
well done ! |
| ||
Here an indented version (just cut & pasted into Jungle Ide) and added a couple of missing ;Strict Global start:Int[] = [0, 308, 0, 75, 0, 180, 2, 10, 400, 510, 30, 96, 0, 0, 0, 640, 90, 18, 8,60,900 , 91, 0, 670, 0, 905, 0] Global indexes:Int[] = [0, 9, 18, 0, 10, 18, 0, 11, 18, 0, 12, 19, 0, 13, 19, 0, 14, 19, 0, 15, 20, 0, 16, 20, 0, 17, 20, 1, 9, 18, 1, 10, 18, 1, 11, 18, 1, 12, 19, 1, 13, 19, 1, 14, 19, 1, 15, 20, 1, 16, 20, 1, 17, 20, 2, 9, 18, 2, 10, 18, 2, 11, 18, 2, 12, 19, 2, 13, 19, 2, 14, 19, 2, 15, 20, 2, 16, 20, 2, 17, 20, 3, 9, 21, 3, 10, 21, 3, 11, 21, 3, 12, 22, 3, 13, 22, 3, 14, 22, 3, 15, 23, 3, 16, 23, 3, 17, 23, 4, 9, 21, 4, 10, 21, 4, 11, 21, 4, 12, 22, 4, 13, 22, 4, 14, 22, 4, 15, 23, 4, 16, 23, 4, 17, 23, 5, 9, 21, 5, 10, 21, 5, 11, 21, 5, 12, 22, 5, 13, 22, 5, 14, 22, 5, 15, 23, 5, 16, 23, 5, 17, 23, 6, 9, 24, 6, 10, 24, 6, 11, 24, 6, 12, 25, 6, 13, 25, 6, 14, 25, 6, 15, 26, 6, 16, 26, 6, 17, 26, 7, 9, 24, 7, 10, 24, 7, 11, 24, 7, 12, 25, 7, 13, 25, 7, 14, 25, 7, 15, 26, 7, 16, 26, 7, 17, 26, 8, 9, 24, 8, 10, 24, 8, 11, 24, 8, 12, 25, 8, 13, 25, 8, 14, 25, 8, 15, 26, 8, 16, 26, 8, 17, 26] Global Number_of_bits:Int[]=[ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 5, 6, 6, 7, 6, 7, 7, 8, 6, 7, 7, 8, 7, 8, 8, 9] Global Highest_bitnumber:Int[]=[ ' Return highest bitnumber + 1 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] Class Myerr Extends Throwable Field msg:string Method New(s:String) msg = s End Method End Class Class sudoku Const RASTERSIZE:= 81 Const FREESIZE:= 27 Field raster:Int[RASTERSIZE] Field free:Int[FREESIZE] Field stack:Int[RASTERSIZE] Field sp:int Field i0:Int, i1:Int, i2:Int Field freebits:Int Field solutioncnt:int Method reset_all_free:Void() For Local i:Int = 0 Until FREESIZE; free[i] = $1ff; Next End Method init_stack:Void() sp = 0 For Local i:Int = 0 Until RASTERSIZE If raster[i] = 0 stack[sp] = i sp += 1 end end End Method init:Void(startraster:Int[]) If startraster.Length <> FREESIZE Throw New Myerr("Startraster length not 27 !!") Local t:Int, z:Int, i:Int, x:Int solutioncnt = 0 sp = 0 reset_all_free For i = 0 Until RASTERSIZE raster[i] = 0; Next x = RASTERSIZE - 1 For i = FREESIZE - 1 To 0 Step - 1 z = startraster[i] For Local j:Int=1 To 3 t = z Mod 10 If t <> 0 set_occupied x, (1 Shl (t - 1)) z /= 10 x -= 1 next Next init_stack End Method New(is:Int[]) init is End Method Method showraster:Void() Local n:Int = 0, v:Int = 0, n2:Int = 0, n3:Int = 0 Local s:String = "" For Local i:Int = 0 Until RASTERSIZE v = v * 10 + Highest_bitnumber[raster[i]] n += 1 If n = 3 If s = "" s += v Else s += ("|" + v) n = 0 v = 0 n2 += 1 EndIf If n2 = 3 Print(s) s = "" n2 = 0 n3 += 1 If n3 = 3 And i <> (RASTERSIZE - 1) n3 = 0 Print("---+---+---") End Next End Method Method set_indexes:Void(pos:Int) pos = (pos Shl 1) + pos 'pos*=3 i0 = indexes[pos + 0] i1 = indexes[pos + 1] i2 = indexes[pos + 2] End Method get_free:Void(pos:Int) set_indexes pos freebits = free[i0] & free[i1] & free[i2] End Method set_free:Void(pos:Int) ' n goes from 1 to 9 Local n:Int = raster[pos] If n = 0 Return raster[pos] = 0 set_indexes pos free[i0] |= n free[i1] |= n free[i2] |= n End Method set_occupied:Void(pos:Int, n:Int) set_indexes pos raster[pos]=n free[i0] ~= n free[i1] ~= n free[i2] ~= n End Method find_best_pos:Int() Local n:Int, oldn:Int = 9, newpos:Int = RASTERSIZE, pos:Int, i:Int, x:Int = -1 Local fb:Int = 0 i = sp - 1 While i >= 0 pos = stack[i] get_free(pos) n = Number_of_bits[freebits] If n = 0 Return - 1 If n = 1 newpos = pos x = i Exit End If n < oldn oldn = n newpos = pos fb = freebits x = i End i -= 1 End sp -= 1 stack[x] = stack[sp] If n > 1 freebits = fb Return newpos End Method solveloop:Void() If sp = 0 If solutioncnt = 0 showraster solutioncnt += 1 Else Throw New Myerr("Aborted. More then 1 solution !!") end Return end Local pos:Int, bm:Int, t:Int pos = find_best_pos() If pos < 0 Return bm = freebits While bm t = 1 Shl (Highest_bitnumber[bm] - 1) set_occupied pos, t solveloop set_free pos bm ~= t Wend stack[sp] = pos sp += 1 end Method solve:Void() init start Print "" solveloop If solutioncnt = 0 Throw New Myerr("No solution found !!") End End Class Function Main:Int() Try Local s:sudoku = New sudoku(start) s.solve Catch ex:Myerr Print ex.msg End Return 0 End Function |