日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数独用计算机控制比数学家还厉害,用pl/sql解决芬兰数学家因卡拉设计的最难数独...

發布時間:2023/12/14 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数独用计算机控制比数学家还厉害,用pl/sql解决芬兰数学家因卡拉设计的最难数独... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近看朋友在玩消滅星星(pop start),想起當年還不是彩屏手機的時候,我喜歡玩數獨游戲.數獨(Sudoku)又稱九宮格,據說來頭很大,起源于河圖洛書,相信大家都有玩過.百度九宮格,

百度百科最后有提到芬蘭數學家因卡拉花費3個月設計出了世界上迄今難度最大的九宮格游戲,而且它只有一個答案,就想挑戰一下.水平有限花了2天時間問題解決,速度還行2秒內就

能解答,發現還是比較簡單的,大概的分為兩段,第一段是找到唯一的那些值填上做為永久值,然后再找唯一值做為永久值,直到找不到唯一值.第二段通過回溯,把可能的值按順序嘗試,不

合適就回退,至到找到最終合適的.

以下腳本及解釋:

DECLARE

--定義數獨行列

TYPE T_ROW IS VARRAY(9) OF NUMBER;

TYPE T_COL_ROW IS VARRAY(9) OF T_ROW;

--初始化數獨

v_init?? T_COL_ROW := T_COL_ROW(T_ROW(8, 0, 0, 0, 0, 0, 0, 0, 0),

T_ROW(0, 0, 3, 6, 0, 0, 0, 0, 0),

T_ROW(0, 7, 0, 0, 9, 0, 2, 0, 0),

T_ROW(0, 5, 0, 0, 0, 7, 0, 0, 0),

T_ROW(0, 0, 0, 0, 4, 5, 7, 0, 0),

T_ROW(0, 0, 0, 1, 0, 0, 0, 3, 0),

T_ROW(0, 0, 1, 0, 0, 0, 0, 6, 8),

T_ROW(0, 0, 8, 5, 0, 0, 0, 1, 0),

T_ROW(0, 9, 0, 0, 0, 0, 4, 0, 0));

--用以存放答案

v_result T_COL_ROW;

--定義一個用以計算小宮里面的同組數據的位置

TYPE T_X IS VARRAY(2) OF NUMBER;

TYPE T_Y IS VARRAY(3) OF T_X;

--用以根據相對位置,算出同組數據的絕對位置

v_xy T_Y := T_Y(T_X(1, 2), T_X(-1, 1), T_X(-1, -2));

x integer;

y integer;

--定義每個點的可能值,i存放列位置,j存放行位置,val存放可能值(可能值里面存放的是多個值,根據cur確認當前是那個),cur的值用于從val中找到當前值

TYPE T_POS IS record(

i?? number,

j?? number,

val varchar2(10),

cur number);

TYPE T_SEL IS TABLE OF T_POS INDEX BY BINARY_INTEGER;

v_sel T_SEL;

v_n???????? varchar2(10);

v_flag????? number := 1;

v_sel_count number := 0;

v_hs??????? number := 0;

BEGIN

--打印問題數獨

dbms_output.put_line('問題:');

FOR i IN 1 .. v_init.COUNT LOOP

FOR j IN 1 .. v_init(i).COUNT LOOP

dbms_output.put(v_init(i) (j) || '? ');

END LOOP;

dbms_output.put_line('');

END LOOP;

--通過循環找唯一值,把唯一值做為永久值,直到找不到唯一值

while v_flag = 1 loop

v_flag := 0;

v_sel.delete;

FOR i IN 1 .. v_init.COUNT LOOP

FOR j IN 1 .. v_init(i).COUNT LOOP

--v_init(i) (j) = 0的是用來填答案的,其它就是永久值

if v_init(i) (j) = 0 then

v_n := '';

--x,y是用來計算除行,列之后還在去對比的同組中的4個值

x := case

when mod(i, 3) = 0 then

3

else

mod(i, 3)

end;

y := case

when mod(j, 3) = 0 then

3

else

mod(j, 3)

end;

--通過循環找到可能值,把可能的值存入v_n

for k in 1 .. 9 loop

if k not in

(--行

v_init(i) (1),

v_init(i) (2),

v_init(i) (3),

v_init(i) (4),

v_init(i) (5),

v_init(i) (6),

v_init(i) (7),

v_init(i) (8),

v_init(i) (9),

--列

v_init(1) (j),

v_init(2) (j),

v_init(3) (j),

v_init(4) (j),

v_init(5) (j),

v_init(6) (j),

v_init(7) (j),

v_init(8) (j),

v_init(9) (j),

--同組另外的四個要對比的值

v_init(i + v_xy(x) (1)) (j + v_xy(y) (1)),

v_init(i + v_xy(x) (1)) (j + v_xy(y) (2)),

v_init(i + v_xy(x) (2)) (j + v_xy(y) (1)),

v_init(i + v_xy(x) (2)) (j + v_xy(y) (2))) then

begin

v_n := v_n || k;

end;

end if;

end loop;

--把可能值的位置,值存入隊列

v_sel_count := v_sel.count + 1;

v_sel(v_sel_count).i := i;

v_sel(v_sel_count).j := j;

v_sel(v_sel_count).val := v_n;

v_sel(v_sel_count).cur := 1;

--如果v_n=1就是唯一值,把這個值永久化,并把v_flag設為1用以再循環一次

--如果v_n=0說明在此位置沒有任何合適的值,說明這個數獨開始的數據有問題

if length(v_n) = 1 then

v_init(i)(j) := to_number(v_n);

v_flag := 1;

elsif length(v_n) = 0 then

dbms_output.put_line('數獨初始化的數據錯誤!');

exit;

end if;

end if;

END LOOP;

END LOOP;

end loop;

--把做過唯一值永久化后的數據賦值給答案數獨

v_result := v_init;

--開始回溯算法通過可能值找最終答案

while v_hs < v_sel.COUNT LOOP

v_hs := v_hs + 1;

--x,y是用來計算除行,列之后還在去對比的同組中的4個值

x := case

when mod(v_sel(v_hs).i, 3) = 0 then

3

else

mod(v_sel(v_hs).i, 3)

end;

y := case

when mod(v_sel(v_hs).j, 3) = 0 then

3

else

mod(v_sel(v_hs).j, 3)

end;

--判斷當前值是否合適,如果不合適,當前位置的可能值向后推進一位,如果當前位置的值已經用完,再后回退,上一層的可能值推進

if to_number(substr(v_sel(v_hs).val, v_sel(v_hs).cur, 1)) in

(v_result(v_sel(v_hs).i) (1),

v_result(v_sel(v_hs).i) (2),

v_result(v_sel(v_hs).i) (3),

v_result(v_sel(v_hs).i) (4),

v_result(v_sel(v_hs).i) (5),

v_result(v_sel(v_hs).i) (6),

v_result(v_sel(v_hs).i) (7),

v_result(v_sel(v_hs).i) (8),

v_result(v_sel(v_hs).i) (9),

v_result(1) (v_sel(v_hs).j),

v_result(2) (v_sel(v_hs).j),

v_result(3) (v_sel(v_hs).j),

v_result(4) (v_sel(v_hs).j),

v_result(5) (v_sel(v_hs).j),

v_result(6) (v_sel(v_hs).j),

v_result(7) (v_sel(v_hs).j),

v_result(8) (v_sel(v_hs).j),

v_result(9) (v_sel(v_hs).j),

v_result(v_sel(v_hs).i + v_xy(x) (1)) (v_sel(v_hs).j + v_xy(y) (1)),

v_result(v_sel(v_hs).i + v_xy(x) (1)) (v_sel(v_hs).j + v_xy(y) (2)),

v_result(v_sel(v_hs).i + v_xy(x) (2)) (v_sel(v_hs).j + v_xy(y) (1)),

v_result(v_sel(v_hs).i + v_xy(x) (2)) (v_sel(v_hs).j + v_xy(y) (2))) then

if v_sel(v_hs).cur < length(v_sel(v_hs).val) then

begin

v_sel(v_hs).cur := v_sel(v_hs).cur + 1;

v_hs := v_hs - 1;

end;

else

if v_hs > 1 then

v_result(v_sel(v_hs).i)(v_sel(v_hs).j) := 0;

v_sel(v_hs).cur := 1;

v_hs := v_hs - 2;

else

dbms_output.put_line('數獨初始化的數據錯誤!');

exit;

end if;

end if;

else

v_result(v_sel(v_hs).i)(v_sel(v_hs).j) := to_number(substr(v_sel(v_hs).val,

v_sel(v_hs).cur,

1));

end if;

END LOOP;

--打印答案數獨

dbms_output.put_line('答案:');

FOR i IN 1 .. v_result.COUNT LOOP

FOR j IN 1 .. v_result(i).COUNT LOOP

dbms_output.put(v_result(i) (j) || '? ');

END LOOP;

dbms_output.put_line('');

END LOOP;

END;

備注:

另外再放兩個數獨,有興趣的可以測試.

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0),

(0, 0, 0, 0, 0, 0, 0, 0, 0)

---------------------------------------

(0, 6, 2, 0, 0, 0, 5, 0, 0),

(3, 5, 0, 0, 0, 0, 0, 0, 7),

(0, 0, 8, 0, 1, 5, 0, 4, 0),

(0, 0, 0, 0, 6, 0, 9, 0, 8),

(9, 0, 0, 0, 0, 0, 0, 2, 0),

(0, 2, 5, 0, 9, 0, 0, 0, 0),

(5, 0, 0, 0, 3, 0, 7, 0, 0),

(0, 8, 0, 0, 0, 0, 0, 5, 6),

(0, 0, 9, 0, 0, 0, 8, 0, 4)

總結

以上是生活随笔為你收集整理的数独用计算机控制比数学家还厉害,用pl/sql解决芬兰数学家因卡拉设计的最难数独...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。