|
刚刚发现顶楼提到的用MODEL解SUDOKU的牛人Anton Scheffer又推出了11GR2的版本:
http://technology.amis.nl/blog/6 ... -subquery-factoring
with x( s, ind ) as
( select sud, instr( sud, ' ' )
from ( select '53 7 6 195 98 6 8 6 34 8 3 17 2 6 6 28 419 5 8 79' sud from dual )
union all
select substr( s, 1, ind - 1 ) || z || substr( s, ind + 1 )
, instr( s, ' ', ind + 1 )
from x
, ( select to_char( rownum ) z
from dual
connect by rownum <= 9
) z
where ind > 0
and not exists ( select null
from ( select rownum lp
from dual
connect by rownum <= 9
)
where z = substr( s, trunc( ( ind - 1 ) / 9 ) * 9 + lp, 1 )
or z = substr( s, mod( ind - 1, 9 ) - 8 + lp * 9, 1 )
or z = substr( s, mod( trunc( ( ind - 1 ) / 3 ), 3 ) * 3
+ trunc( ( ind - 1 ) / 27 ) * 27 + lp
+ trunc( ( lp - 1 ) / 3 ) * 6
, 1 )
)
)
select s
from x
where ind = 0
/
我没有11GR2, 用如下办法来模拟一下:
CREATE GLOBAL TEMPORARY TABLE SUD (lvl NUMBER,S VARCHAR2(100), IND NUMBER) ON COMMIT PRESERVE ROWS;
CREATE OR REPLACE PROCEDURE P_SUD (p_str IN VARCHAR2)
AS
v_level NUMBER :=1;
v_answer VARCHAR2(100);
BEGIN
DELETE SUD;
INSERT INTO SUD VALUES(1,p_str,INSTR(p_str,' '));
LOOP
INSERT INTO SUD
select v_level+1
, substr( s, 1, ind - 1 ) || z || substr( s, ind + 1 )
, instr( s, ' ', ind + 1 )
from SUD
, ( select to_char( rownum ) z
from dual
connect by rownum <= 9
) z
where lvl =v_level AND ind > 0
and not exists ( select null
from ( select rownum lp
from dual
connect by rownum <= 9
)
where z = substr( s, trunc( ( ind - 1 ) / 9 ) * 9 + lp, 1 )
or z = substr( s, mod( ind - 1, 9 ) - 8 + lp * 9, 1 )
or z = substr( s, mod( trunc( ( ind - 1 ) / 3 ), 3 ) * 3
+ trunc( ( ind - 1 ) / 27 ) * 27 + lp
+ trunc( ( lp - 1 ) / 3 ) * 6
, 1 )
);
EXIT WHEN SQL%ROWCOUNT=0;
v_level := v_level+1;
END LOOP;
SELECT s
INTO v_answer
FROM sud
WHERE ind = 0;
DBMS_OUTPUT.PUT_LINE(v_answer);
END;
/
测试:
EXEC P_SUD('53 7 6 195 98 6 8 6 34 8 3 17 2 6 6 28 419 5 8 79');
输出:
534678912672195348198342567859761423426853791713924856961537284287419635345286179
写法极其简练,他用的是未经优化的穷尽法,因此效率略低,但我不知道在11GR2中表现如何,有环境的可以试一下。
|
|