Sudoku: Difference between revisions
Content added Content deleted
m (→{{header|FutureBasic}}: Remove unsupported 'ConsoleWindow) |
m (→{{header|FutureBasic}}: remove 'dim as' and update millisecond timer) |
||
Line 5,297: | Line 5,297: | ||
More code in this one, but faster execution: |
More code in this one, but faster execution: |
||
<pre> |
<pre> |
||
include "ConsoleWindow" |
|||
include "Tlbx Timer.incl" |
|||
begin globals |
begin globals |
||
_digits = 9 |
_digits = 9 |
||
Line 5,308: | Line 5,305: | ||
begin record Board |
begin record Board |
||
Boolean f(_digits,_digits,_digits) |
|||
char match(_digits,_digits) |
|||
pointer previousBoard // singly-linked list used to discover repetitions |
|||
dim && |
dim && |
||
end record |
end record |
||
Board quiz |
|||
CFTimeInterval t |
|||
dim as long t |
|||
dim as double sProgStartTime |
|||
end globals |
end globals |
||
// 'ordinary' timer used for playing |
|||
local fn Milliseconds as long // time in ms since prog start |
|||
'~'1 |
|||
dim as UnsignedWide us |
|||
long if ( sProgStartTime == 0.0 ) |
|||
Microseconds( @us ) |
|||
sProgStartTime = 4294967296.0*us.hi + us.lo |
|||
end if |
|||
Microseconds( @us ) |
|||
end fn = (4294967296.0*us.hi + us.lo - sProgStartTime)'*1e-3 |
|||
local fn InitMilliseconds |
|||
'~'1 |
|||
sProgStartTime = 0.0 |
|||
fn Milliseconds |
|||
end fn |
|||
local mode |
local mode |
||
local fn CopyBoard( source as ^Board, dest as ^Board ) |
local fn CopyBoard( source as ^Board, dest as ^Board ) |
||
BlockMoveData( source, dest, sizeof( Board ) ) |
|||
'~'1 |
|||
dest.previousBoard = source // linked list |
|||
BlockMoveData( source, dest, sizeof( Board ) ) |
|||
dest.previousBoard = source // linked list |
|||
end fn |
end fn |
||
local fn prepare( b as ^Board ) |
local fn prepare( b as ^Board ) |
||
short i, j, n |
|||
'~'1 |
|||
dim as short i, j, n |
|||
for i = 1 to _digits |
|||
for |
for j = 1 to _digits |
||
for |
for n = 1 to _digits |
||
b.match[i, j] = 0 |
|||
for n = 1 to _digits |
|||
b. |
b.f[i, j, n] = _true |
||
next n |
|||
b.f[i, j, n] = _true |
|||
next |
next j |
||
next |
next i |
||
next i |
|||
end fn |
end fn |
||
local fn printBoard( b as ^Board ) |
local fn printBoard( b as ^Board ) |
||
short i, j |
|||
'~'1 |
|||
dim as short i, j |
|||
for i = 1 to _digits |
|||
for |
for j = 1 to _digits |
||
Print b.match[i, j]; |
|||
for j = 1 to _digits |
|||
next j |
|||
Print b.match[i, j]; |
|||
print |
|||
next j |
|||
next i |
|||
print |
|||
next i |
|||
end fn |
end fn |
||
local fn verifica( b as ^Board ) |
local fn verifica( b as ^Board ) |
||
short i, j, n, first, x, y, ii |
|||
'~'1 |
|||
Boolean check |
|||
dim as short i, j, n, first, x, y, ii |
|||
dim as boolean check |
|||
check = _true |
|||
check = _true |
|||
for i = 1 to _digits |
|||
for |
for j = 1 to _digits |
||
if ( b.match[i, j] == 0 ) |
|||
for j = 1 to _digits |
|||
check = _false |
|||
long if ( b.match[i, j] == 0 ) |
|||
for n = 1 to _digits |
|||
check = _false |
|||
if ( b.f[i, j, n] != _false ) |
|||
for n = 1 to _digits |
|||
check = _true |
|||
long if ( b.f[i, j, n] != _false ) |
|||
end if |
|||
check = _true |
|||
next n |
|||
end if |
|||
if ( check == _false ) then exit fn |
|||
next n |
|||
end if |
|||
if ( check == _false ) then exit fn |
|||
next j |
|||
end if |
|||
next |
next i |
||
next i |
|||
check = _true |
|||
for j = 1 to _digits |
|||
check = _true |
|||
for |
for n = 1 to _digits |
||
first = 0 |
|||
for i = 1 to _digits |
|||
first = 0 |
|||
if ( b.match[i, j] == n ) |
|||
for i = 1 to _digits |
|||
if ( first == 0 ) |
|||
first = i |
|||
else |
|||
first = i |
|||
check = _false |
|||
xelse |
|||
exit fn |
|||
check = _false |
|||
end if |
|||
exit fn |
|||
end if |
end if |
||
next i |
|||
end if |
|||
next |
next n |
||
next |
next j |
||
next j |
|||
for i = 1 to _digits |
|||
for |
for n = 1 to _digits |
||
first = 0 |
|||
for j = 1 to _digits |
|||
first = 0 |
|||
if ( b.match[i, j] == n ) |
|||
for j = 1 to _digits |
|||
if ( first == 0 ) |
|||
first = j |
|||
else |
|||
first = j |
|||
check = _false |
|||
xelse |
|||
exit fn |
|||
check = _false |
|||
end if |
|||
exit fn |
|||
end if |
end if |
||
next j |
|||
end if |
|||
next |
next n |
||
next |
next i |
||
next i |
|||
for x = 0 to ( _nSetH - 1 ) |
|||
for |
for y = 0 to ( _nSetV - 1 ) |
||
first = 0 |
|||
for ii = 0 to ( _digits - 1 ) |
|||
first = 0 |
|||
i = x * _setH + ii mod _setH + 1 |
|||
for ii = 0 to ( _digits - 1 ) |
|||
j = y * _setV + ii / _setH + 1 |
|||
if ( b.match[i, j] == n ) |
|||
if ( first == 0 ) |
|||
first = j |
|||
else |
|||
first = j |
|||
check = _false |
|||
xelse |
|||
exit fn |
|||
check = _false |
|||
end if |
|||
exit fn |
|||
end if |
end if |
||
next ii |
|||
end if |
|||
next |
next y |
||
next |
next x |
||
next x |
|||
end fn = check |
end fn = check |
||
local fn setCell( b as ^Board, x as short, y as short, n as short) as boolean |
local fn setCell( b as ^Board, x as short, y as short, n as short) as boolean |
||
short i, j, rx, ry |
|||
Boolean check |
|||
b.match[x, y] = n |
b.match[x, y] = n |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
b.f[x, i, n] = _false |
b.f[x, i, n] = _false |
||
b.f[i, y, n] = _false |
b.f[i, y, n] = _false |
||
next i |
next i |
||
rx = (x - 1) / _setH |
rx = (x - 1) / _setH |
||
ry = (y - 1) / _setV |
ry = (y - 1) / _setV |
||
for i = 1 to _setH |
for i = 1 to _setH |
||
for j = 1 to _setV |
for j = 1 to _setV |
||
b.f[ rx * _setH + i, ry * _setV + j, n ] = _false |
b.f[ rx * _setH + i, ry * _setV + j, n ] = _false |
||
next j |
next j |
||
next i |
next i |
||
check = fn verifica( #b ) |
check = fn verifica( #b ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end fn = check |
end fn = check |
||
local fn solve( b as ^Board ) |
local fn solve( b as ^Board ) |
||
short i, j, n, first, x, y, ii, ppi, ppj |
|||
Boolean check |
|||
check = _true |
check = _true |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
if ( b.match[i, j] == 0 ) |
|||
first = 0 |
first = 0 |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
if ( b.f[i, j, n] != _false ) |
|||
if ( first == 0 ) |
|||
first = n |
first = n |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next n |
next n |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, i, j, first ) |
check = fn setCell( #b, i, j, first ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
end if |
end if |
||
next j |
next j |
||
next i |
next i |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
first = 0 |
first = 0 |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
if ( b.match[i, j] == n ) then exit for |
if ( b.match[i, j] == n ) then exit for |
||
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 ) |
|||
if ( first == 0 ) |
|||
first = j |
first = j |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next j |
next j |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, i, first, n ) |
check = fn setCell( #b, i, first, n ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
next n |
next n |
||
next i |
next i |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
first = 0 |
first = 0 |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
if ( b.match[i, j] == n ) then exit for |
if ( b.match[i, j] == n ) then exit for |
||
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 ) |
|||
if ( first == 0 ) |
|||
first = i |
first = i |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next i |
next i |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, first, j, n ) |
check = fn setCell( #b, first, j, n ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
next n |
next n |
||
next j |
next j |
||
for x = 0 to ( _nSetH - 1 ) |
for x = 0 to ( _nSetH - 1 ) |
||
for y = 0 to ( _nSetV - 1 ) |
for y = 0 to ( _nSetV - 1 ) |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
first = 0 |
first = 0 |
||
for ii = 0 to ( _digits - 1 ) |
for ii = 0 to ( _digits - 1 ) |
||
i = x * _setH + ii mod _setH + 1 |
i = x * _setH + ii mod _setH + 1 |
||
j = y * _setV + ii / _setH + 1 |
j = y * _setV + ii / _setH + 1 |
||
if ( b.match[i, j] == n ) then exit for |
if ( b.match[i, j] == n ) then exit for |
||
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 ) |
|||
if ( first == 0 ) |
|||
first = n |
first = n |
||
ppi = i |
ppi = i |
||
ppj = j |
ppj = j |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next ii |
next ii |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, ppi, ppj, n ) |
check = fn setCell( #b, ppi, ppj, n ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
next n |
next n |
||
next y |
next y |
||
next x |
next x |
||
end fn = check |
end fn = check |
||
local fn resolve( b as ^Board ) |
local fn resolve( b as ^Board ) |
||
Boolean check, daFinire |
|||
long i, j, n |
|||
Board localBoard |
|||
check = fn solve(b) |
check = fn solve(b) |
||
if ( check == _false ) |
|||
exit fn |
exit fn |
||
end if |
end if |
||
daFinire = _false |
daFinire = _false |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
if ( b.match[i, j] == 0 ) |
|||
daFinire = _true |
daFinire = _true |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
if ( b.f[i, j, n] != _false ) |
|||
fn CopyBoard( b, @localBoard ) |
fn CopyBoard( b, @localBoard ) |
||
check = fn setCell(@localBoard, i, j, n) |
check = fn setCell(@localBoard, i, j, n) |
||
if ( check != _false ) |
|||
check = fn resolve( @localBoard ) |
check = fn resolve( @localBoard ) |
||
if ( check == -1 ) |
|||
fn CopyBoard( @localBoard, b ) |
fn CopyBoard( @localBoard, b ) |
||
exit fn |
exit fn |
||
end if |
end if |
||
end if |
end if |
||
end if |
end if |
||
next n |
next n |
||
end if |
end if |
||
next j |
next j |
||
next i |
next i |
||
if daFinire |
|||
else |
|||
xelse |
|||
check = -1 |
check = -1 |
||
end if |
end if |
||
end fn = check |
end fn = check |
||
fn InitMilliseconds |
|||
fn prepare( @quiz ) |
fn prepare( @quiz ) |
||
Line 5,670: | Line 5,642: | ||
DATA 2,8,0,1,3,0,0,0,0 |
DATA 2,8,0,1,3,0,0,0,0 |
||
short i, j, d |
|||
for i = 1 to _digits |
for i = 1 to _digits |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
read d |
read d |
||
fn setCell(@quiz, j, i, d) |
fn setCell(@quiz, j, i, d) |
||
next j |
next j |
||
next i |
next i |
||
Line 5,681: | Line 5,653: | ||
fn printBoard( @quiz ) |
fn printBoard( @quiz ) |
||
print : print "-------------------" : print |
print : print "-------------------" : print |
||
Boolean check |
|||
t = fn |
t = fn CACurrentMediaTime |
||
check = fn resolve(@quiz) |
check = fn resolve(@quiz) |
||
t = fn |
t = (fn CACurrentMediaTime - t) * 1000 |
||
if ( check ) |
if ( check ) |
||
print "solution:"; str$( t |
print "solution:"; str$( t ) + " ms" |
||
else |
else |
||
print "No solution found" |
print "No solution found" |
||
end if |
end if |
||
fn printBoard( @quiz ) |
fn printBoard( @quiz ) |
||
HandleEvents |
|||
</pre> |
</pre> |
||