Hi,

The speedest version of the sudoku, staying in the limit of lisibility
would include 3 nested "with",

timing with medium sudoku example  :
'1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..'
2 nested with = 3.32 sec
1 nested with = 1.7sec

(1 nested with which could be 3 nested with) = 1.09 sec (see below 'annexe
1')

3 nested with  .... well I get a "MemoryError: " event on the simplest
example. (see below  'annexe 2')
==> nobody in real life would do that, would he ?

Anyway, when I was trying to implement "fake" CTE, I was :
- creating views when the CTE was like " x as (select ...)"
- creating table when the cte was like "x(r) as (select ...)"
- creating table with index when the cte was like (x(r INTEGER

*PRIMARY KEY) as (select ...)"*


*==> So, if the if sudoku solving at the maximum speed with only virtual
table was a DEAD or ALIVE situation, I may suggest "embrassing and
extending" the CTE standard with a similar trick.*


**** example of "optimized" stupid-brut force sudoku 1 with **

drop table if exists ok;
create table ok(c,n);
CREATE INDEX ok_i
on ok (c, n);
with digits(z, lp) AS (
    VALUES('1', 1),('2', 2) ,('3', 3),('4', 4),('5', 5),('6', 6),('7',
7),('8', 8),('9', 9)
    )
    ,y(r) as (WITH RECURSIVE col(c) AS (
   select 81  as c
   union all
   select c-1 from col where c>1
   )  select * from col)
, neighbors(r,n) as (select r, ((r-1)/9)*9 + lp from y, digits
union all select r, ((r-1)%9) + (lp-1)*9 + 1 from y, digits
union all select r, (((r-1)/3) % 3) * 3
       + ((r-1)/27) * 27 + lp
       + ((lp-1) / 3) * 6 from y, digits)
, goods (r,n) as (select * from neighbors where r <>n)
insert into ok select distinct * from goods;

-- easy   (0 sec)
'53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79'
-- medium (2 sec)
'1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..'
-- hard   (200 s)
'8..........36......7..9.2...5...7.......457.....1...3...1....68..85...1..9....4..'

WITH RECURSIVE input(sud) AS (
   VALUES(
 
'1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..'
)
),

/* A table filled with digits 1..9, inclusive. */
digits(z, lp) AS (
    VALUES('1', 1),('2', 2) ,('3', 3),('4', 4),('5', 5),('6', 6),('7',
7),('8', 8),('9', 9)
    ),

/* The tricky bit. */
x(s, ind) AS (
   SELECT sud, instr(sud, '.') FROM input
   UNION ALL
   SELECT
   substr(s, 1, ind-1) || z || substr(s, ind+1),
   instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )
   FROM x, digits AS z
   WHERE ind>0
   AND NOT EXISTS (
     SELECT 1 FROM ok AS lp
     WHERE ind=lp.c and  z.z = substr(s, n, 1)
   )
)

SELECT * FROM x  WHERE ind=0;

**** same with 3 nested with ... blow up even on the simplest case (bug of
me ? ) ***
drop table if exists ok;
create table ok(c,n);
CREATE INDEX ok_i
on ok (c, n);
with digits(z, lp) AS (
    VALUES('1', 1),('2', 2) ,('3', 3),('4', 4),('5', 5),('6', 6),('7',
7),('8', 8),('9', 9)
    )
    ,y(r) as (WITH RECURSIVE col(c) AS (
   select 81  as c
   union all
   select c-1 from col where c>1
   )  select * from col)
, neighbors(r,n) as (select r, ((r-1)/9)*9 + lp from y, digits
union all select r, ((r-1)%9) + (lp-1)*9 + 1 from y, digits
union all select r, (((r-1)/3) % 3) * 3
       + ((r-1)/27) * 27 + lp
       + ((lp-1) / 3) * 6 from y, digits)
, goods (r,n) as (select * from neighbors where r <>n)


,input(sud) AS (
   VALUES(
-- 
'1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..'
'53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79')
),

/* A table filled with digits 1..9, inclusive. */
--digits(z, lp) AS (
--    VALUES('1', 1),('2', 2) ,('3', 3),('4', 4),('5', 5),('6', 6),('7',
7),('8', 8),('9', 9)
--    ),

/* The tricky bit. */
x(s, ind) AS (
   SELECT sud, instr(sud, '.') FROM input
   UNION ALL
   SELECT
   substr(s, 1, ind-1) || z || substr(s, ind+1),
   instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )
   FROM x, digits AS z
   WHERE ind>0
   AND NOT EXISTS (
     SELECT 1 FROM ok AS lp
     WHERE ind=lp.c and  z.z = substr(s, n, 1)
   )
)

SELECT * FROM x  WHERE ind=0;
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to