|
|
本帖最后由 wxy0327 于 2021-7-26 18:19 编辑
已改写,但比Oracle慢了4倍多,900毫秒左右- DO $DECLARE
- i int;
- j int;
- k int;
- s _varchar(10);
-
- used_c int[][]:=array_fill(0,array[9,9]); --- in this column whether the number has been used
- used_r int[][]:=array_fill(0,array[9,9]); --- in this row whether the number has been used
- used_a int[][]:=array_fill(0,array[9,9]); --- in this area whether the number has been used
-
- area int[][]:=array_fill(0,array[9,9]); ---- mapping from row, column to area
-
- v_cnt int :=0;
-
- slot_value int[][]:=array_fill(0,array[100,100]);
-
- slot_r int[];
- slot_c int[];
-
- v_cnt2 int :=0;
-
- v_idx int;
-
- slot_value_idx int[]=array_fill(1,array[60]);
-
- BEGIN
- s[1]:= '8 ';
- s[2]:= ' 36 ';
- s[3]:= ' 7 9 2 ';
- s[4]:= ' 5 7 ';
- s[5]:= ' 457 ';
- s[6]:= ' 1 3 ';
- s[7]:= ' 1 68';
- s[8]:= ' 85 1 ';
- s[9]:= ' 9 4 ';
- FOR i IN 1..9 LOOP
- FOR j IN 1..9 LOOP
- area[i][j] := (CEIL(i::numeric/3::numeric)-1)*3 + CEIL(j::numeric/3::numeric);
- --raise notice '%.%',i,j;
- --raise notice '%',area[i][j];
- END LOOP;
- END LOOP;
- FOR i IN 1..9 LOOP
- FOR j IN 1..9 LOOP
- k := (case when TRIM(SUBSTRing(s[i],j,1))='' then '0' else TRIM(SUBSTRing(s[i],j,1)) end)::int;
- IF k>0 THEN
- used_c[j][k] :=1;
- used_r[i][k] :=1;
- used_a[area[i][j]][k] :=1;
- --raise notice 'aaaaaaaaaa';
- END IF;
- END LOOP;
- END LOOP;
-
- FOR i IN 1..9 LOOP
- FOR j IN 1..9 LOOP
- IF SUBSTRing(s[i],j,1)=' ' THEN
- v_cnt := v_cnt+1;
-
- v_cnt2 :=0;
-
- FOR k IN 1..9 LOOP
- IF used_c[j][k] = 0 AND used_r[i][k] = 0 AND used_a[area[i][j]][k] = 0 THEN ---- possible value found for this slot
- v_cnt2 := v_cnt2 +1;
- slot_value[v_cnt][v_cnt2] := k;
- --raise info 'slot_value[v_cnt][v_cnt2]: %',slot_value[v_cnt][v_cnt2];
- END IF;
- END LOOP;
-
- IF v_cnt2 = 0 THEN
- RAISE EXCEPTION '-20001,invalid sudoku at %,%',i,j;
- END IF;
-
- IF v_cnt2 = 1 THEN ---- there's only one value for this slot, it's the answer
- k := slot_value[v_cnt][1];
- used_c[j][k] :=1;
- used_r[i][k] :=1;
- used_a[area[i][j]][k] :=1;
- v_cnt := v_cnt - 1;
-
- s[i] := SUBSTRing(s[i],1,j-1) ||k|| SUBSTRing(s[i],j+1);
-
- --raise notice 'bbbbbbbbbb';
- ELSE
- slot_r[v_cnt] := i; ---- position of this slot
- slot_c[v_cnt] := j;
- END IF;
-
- END IF;
- END LOOP;
- END LOOP;
-
- --raise notice '00000000000--%',s;
- --raise notice '-----------------';
- ---- initialize the value indexes of slots
- /*v_idx := 1;
- WHILE slot_value[v_idx][1] <>0 LOOP
- slot_value_idx[v_idx] := 1;
- -- DBMS_OUTPUT.PUT_LINE(v_idx||','||slot_value[v_idx].FIRST);
- v_idx := v_idx+1;
- raise notice '111--%---%',v_idx,slot_value_idx[v_idx];
- -- DBMS_OUTPUT.PUT_LINE(v_idx||','||slot_value.NEXT[v_idx]);
- END LOOP;*/
-
- --raise notice '111--%',slot_value_idx[60];
-
- v_idx := slot_value[1][1];
- WHILE slot_value[v_idx][1] <>0 LOOP
-
- --indx2:=1;
-
- --raise notice '----------';
- WHILE slot_value_idx[v_idx]<>0 LOOP ---- try all values for this slot
-
- --raise notice '+++++++%',slot_value_idx[v_idx];
-
- i := slot_r[v_idx];
- j := slot_c[v_idx];
- k := slot_value[v_idx][slot_value_idx[v_idx]];
-
- --raise notice 'v_idx : % i : % j : % k : %',v_idx,i,j,k;
-
- --raise notice 'v_idx : % used_c[j][k] : % uused_r[i][k] : % used_a[area[i][j]][k] : %',v_idx,used_c[j][k],used_r[i][k],used_a[area[i][j]][k];
-
- IF used_c[j][k] = 0 AND used_r[i][k] = 0 AND used_a[area[i][j]][k] = 0 THEN ---- possible value found for this slot
- --raise notice 'mmmmmmmmmm';
- used_c[j][k] := 1;
- used_r[i][k] := 1;
- used_a[area[i][j]][k] :=1;
- EXIT;
- END IF;
- /*if slot_value[indx2][1] =0 and indx2>1 then
- EXIT;
- end if;*/
-
- --indx2:=indx2+1;
- slot_value_idx[v_idx] := case when slot_value[v_idx][slot_value_idx[v_idx]+1] = 0 then 0 else slot_value_idx[v_idx]+1 end;
- --raise notice '0000--%,%,%',v_idx,slot_value_idx[v_idx],case when slot_value[v_idx][slot_value_idx[v_idx]+1] = 0 then 0 else slot_value_idx[v_idx]+1 end;
- -- DBMS_OUTPUT.PUT_LINE(v_idx||','||slot_value_idx[v_idx]||','||slot_value[v_idx].NEXT(slot_value_idx[v_idx]));
- END LOOP;
- --raise notice '0000000--%',v_idx;
- IF slot_value_idx[v_idx]=0 THEN ---- all values tried but none is the answer
- --raise notice '-----------------';
-
- slot_value_idx[v_idx] := slot_value[1][1]; --- reset the index of this slot
-
- -- DBMS_OUTPUT.PUT_LINE(v_idx||','||slot_value[v_idx].FIRST);
- v_idx := v_idx-1; --- go back and release the last slot
- --raise notice '111111--%',v_idx;
- IF slot_value[v_idx][1] =0 THEN ----- no anwer found
- raise notice 'No Answer Found!';
- EXIT;
- END IF;
-
- i := slot_r[v_idx];
- j := slot_c[v_idx];
- k := slot_value[v_idx][slot_value_idx[v_idx]];
-
- used_c[j][k] := 0;
- used_r[i][k] := 0;
- used_a[area[i][j]][k] :=0;
-
- --indx2:=indx2+1;
- slot_value_idx[v_idx] := case when slot_value[v_idx][slot_value_idx[v_idx]+1] = 0 then 0 else slot_value_idx[v_idx]+1 end;
-
- --raise notice '1111--%,%,%',v_idx,slot_value_idx[v_idx],case when slot_value[v_idx][slot_value_idx[v_idx]+1] = 0 then 0 else slot_value_idx[v_idx]+1 end;
-
- ELSE
- --raise notice '-----------------';
- --if v_idx+1 = 61 then
- --v_idx:=0;
- --else
- v_idx := v_idx+1;
- --end if;
- --raise notice '222222--%',v_idx;
-
- IF slot_value[v_idx][1] =0 THEN ----- all slots tried and found an answer
- v_idx := slot_value[1][1];
- --raise notice '333333--%',v_idx;
- WHILE slot_value[v_idx][1] <>0 and v_idx<>61 LOOP
-
- i := slot_r[v_idx];
- j := slot_c[v_idx];
- k := slot_value[v_idx][slot_value_idx[v_idx]];
- s[i] := SUBSTRing(s[i],1,j-1) || k || SUBSTRing(s[i],j+1);
-
- v_idx := v_idx+1;
- --raise notice 'sssssssssssss--%',s[i];
- --raise notice '4444444--%',v_idx;
- --raise notice 'slot_value_idx[v_idx] : %',slot_value_idx[v_idx];
- --raise notice 'v_idx : % i : % j : % k : %',v_idx,i,j,k;
-
- END LOOP;
-
- raise notice 'Answer Found:';
- FOR i IN 1..9 LOOP
- raise notice '%',s[i];
- END LOOP;
-
- EXIT;
- END IF;
-
- END IF;
- --raise notice '333--%',v_idx;
- END LOOP;
-
- END$;
复制代码 |
|