トップページに戻る    前のSQLパズルへ

再帰with句10 数独を解く

SQLパズル

数独を解きます。


SQL

with work(val) as(
values('080701050'
    || '002040900'
    || '930000074'
    || '800104006'
    || '006000100'
    || '700903008'
    || '240000015'
    || '007050300'
    || '050807040')),
rec(LV,Val) as(
select 1,Val from work
union all
select LV+1,
case when substr(Val,LV,1) = '0'
     then overLay(Val,cnt,LV,OCTETS)
     else Val end
from rec a,
(values('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9')) as b(cnt)
where LV <= 81
  and (substr(Val,LV,1) = '0' or b.cnt='1')
  and (substr(Val,LV,1) !='0'
    or (locate(cnt,substr(Val,(LV-1)/9*9+1    ,9)) = 0 /*横チェック*/
    and locate(cnt,substr(Val,mod(LV-1,9)+1   ,1)) = 0 /*縦チェック*/
    and locate(cnt,substr(Val,mod(LV-1,9)+1+ 9,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)+1+18,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)+1+27,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)+1+36,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)+1+45,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)+1+54,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)+1+63,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)+1+72,1)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)/3*3+1+9*(((LV-1)/9)/3*3)   ,3)) = 0 /*正方形チェック*/
    and locate(cnt,substr(Val,mod(LV-1,9)/3*3+1+9*(((LV-1)/9)/3*3)+ 9,3)) = 0
    and locate(cnt,substr(Val,mod(LV-1,9)/3*3+1+9*(((LV-1)/9)/3*3)+18,3)) = 0)))
select * from rec
 where LV = 81+1;


解説

手続き型言語を使ったほうが楽そうですねぇ
C#のサンプル集 8-8 数独
Javaアルゴリズムパズル 3-7 数独
PostgreSQLパズル 再帰with句10 数独を解く

実行結果
684791253572348961931526874823174596496285137715963428248639715167452389359817642