|
|
原帖由 newkid 于 2009-11-18 07:53 发表 ![]()
再装修一下,尽早退出循环:
CREATE OR REPLACE PACKAGE cube_8 AS
PROCEDURE run_cube(p_x IN NUMBER,p_y IN NUMBER, p_target_layout VARCHAR2);
END cube_8;
/
CREATE OR REPLACE PACKAGE BODY cube_8 AS
TYPE t_str IS TABLE OF VARCHAR2(10) INDEX BY VARCHAR2(9);
g_added_layout t_str;
TYPE t_board IS RECORD (
parent_id VARCHAR2(10)
,layout VARCHAR2(9)
,steps NUMBER
);
TYPE tb_board IS TABLE OF t_board INDEX BY VARCHAR2(10);
g_board tb_board;
g_target VARCHAR2(9);
g_found BOOLEAN;
PROCEDURE show_board (p_start IN VARCHAR2) IS
lv_id VARCHAR2(9):=p_start;
lv_layout VARCHAR2(9);
lv_result t_str;
BEGIN
WHILE lv_id'0' LOOP
lv_result(lv_result.COUNT+1) := lv_id;
lv_id := g_board(lv_id).parent_id;
END LOOP;
FOR i IN REVERSE 1..lv_result.COUNT LOOP
--lv_layout := TRANSLATE(g_board(lv_result(i)).layout, '1234560', 'WWBBRRE');
lv_layout := g_board(lv_result(i)).layout;
dbms_output.put_line('====' ||g_board(lv_result(i)).steps || '====');
dbms_output.put_line('. ' || substr(lv_layout, 1, 3)||' '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 1, 3));
dbms_output.put_line('. ' || substr(lv_layout, 4, 3)||' '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 4, 3));
dbms_output.put_line('. ' || substr(lv_layout, 7, 3)||' '|| substr(TRANSLATE(lv_layout,'1234560','WWBBRRE'), 7, 3));
dbms_output.new_line;
END LOOP;
END;
PROCEDURE add_board (p_layout VARCHAR2, p_parent_id VARCHAR2, p_steps IN NUMBER)
AS
lv_cnt NUMBER := g_board.COUNT+1;
BEGIN
g_board(lv_cnt).parent_id := p_parent_id;
g_board(lv_cnt).layout := p_layout;
g_board(lv_cnt).steps := p_steps;
g_added_layout(p_layout):='1';
IF TRANSLATE(p_layout, '1234560', 'WWBBRRE') = g_target THEN
show_board(lv_cnt);
g_found := TRUE;
END IF;
END add_board;
PROCEDURE add_next_boards(p_layout IN VARCHAR2, p_parent_id VARCHAR2, p_steps IN NUMBER) IS
pos NUMBER;
PROCEDURE new_layout(p_layout IN VARCHAR2,a IN NUMBER,b IN NUMBER, p_c1 IN VARCHAR2, p_c2 IN VARCHAR2)
AS
lv_new_layout VARCHAR2(9):= substr(p_layout, 1, a - 1)
||p_c1
||substr(p_layout,a + 1,b - a - 1)
||p_c2
||substr(p_layout,b + 1);
BEGIN
BEGIN
IF g_added_layout(lv_new_layout)='1' THEN
RETURN;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
add_board(lv_new_layout,p_parent_id,p_steps);
RETURN;
END new_layout;
BEGIN
pos := instr(p_layout, '0');
-- blank block up movable
IF pos > 3 THEN
new_layout(p_layout, pos-3, pos,'0',SUBSTR('645231',SUBSTR(p_layout,pos-3,1),1));
END IF;
-- blank block down movable
IF pos < 7 THEN
new_layout(p_layout, pos, pos + 3,SUBSTR('645231',SUBSTR(p_layout,pos+3,1),1),'0');
END IF;
-- blank block left movable
IF pos NOT IN (1, 4, 7) THEN
new_layout(p_layout, pos-1, pos,'0',SUBSTR('351624',SUBSTR(p_layout,pos-1,1),1));
END IF;
-- blank block right movable
IF pos NOT IN (3, 6, 9) THEN
new_layout(p_layout, pos, pos + 1,SUBSTR('351624',SUBSTR(p_layout,pos+1,1),1),'0');
END IF;
END;
PROCEDURE run_cube(p_x IN NUMBER,p_y IN NUMBER, p_target_layout VARCHAR2)
AS
lv_current NUMBER;
BEGIN
-- empty temporary tables
g_added_layout.DELETE;
g_board.DELETE;
g_found := FALSE;
g_target := p_target_layout;
add_board(RPAD(LPAD('0',(p_y-1)*3+p_x,'1'),'9','1'),'0',0);
lv_current :=1;
WHILE NOT g_found LOOP
add_next_boards(g_board(lv_current).layout, lv_current,g_board(lv_current).steps+1);
lv_current := lv_current +1;
IF lv_current>g_board.COUNT THEN
dbms_output.put_line('no result!');
EXIT;
END IF;
END LOOP;
END;
END cube_8;
/
现在第五个用55秒。
旋转、移位效率比较高。但不知为什么,总报内存不够。
我的机器配置:
Processor: Intel(R) Core(TM)2 Duo CPU E7400 @ 2.8Gz(2 CPUs)
Memory: 2036MB RAM
测试:
EXEC cube_8.run_cube(1,2,'WWWEWWWWW');
EXEC cube_8.run_cube(2,1,'RBWRWWEWW');
EXEC cube_8.run_cube(3,3,'WBWBRERBR');
EXEC cube_8.run_cube(3,3,'BWRBWRBER');
EXEC cube_8.run_cube(2,1,'BBBBRBBRE');
EXEC cube_8.run_cube(1,1,'RRRWWWRRE');
EXEC cube_8.run_cube(2,1,'RRRBWBRRE');
EXEC cube_8.run_cube(3,2,'RRRWEWRRR');
结果:
TEST@orcl> EXEC cube_8.run_cube(1,2,'WWWEWWWWW');
====0====
. 111 WWW
. 011 EWW
. 111 WWW
PL/SQL 过程已成功完成。
已用时间: 00: 00: 00.20
TEST@orcl> EXEC cube_8.run_cube(2,1,'RBWRWWEWW');
====0====
. 101 WEW
. 111 WWW
. 111 WWW
====1====
. 031 EBW
. 111 WWW
. 111 WWW
====2====
. 631 RBW
. 011 EWW
. 111 WWW
====3====
. 631 RBW
. 611 RWW
. 011 EWW
PL/SQL 过程已成功完成。
已用时间: 00: 00: 00.04
TEST@orcl> EXEC cube_8.run_cube(3,3,'WBWBRERBR');
====0====
. 111 WWW
. 111 WWW
. 110 WWE
====1====
. 111 WWW
. 110 WWE
. 116 WWR
====2====
. 111 WWW
. 103 WEB
. 116 WWR
====3====
. 111 WWW
. 163 WRB
. 106 WER
====4====
. 111 WWW
. 163 WRB
. 036 EBR
====5====
. 111 WWW
. 063 ERB
. 636 RBR
====6====
. 111 WWW
. 403 BEB
. 636 RBR
====7====
. 101 WEW
. 463 BRB
. 636 RBR
====8====
. 031 EBW
. 463 BRB
. 636 RBR
====9====
. 231 WBW
. 063 ERB
. 636 RBR
====10====
. 231 WBW
. 403 BEB
. 636 RBR
====11====
. 231 WBW
. 453 BRB
. 606 RER
====12====
. 231 WBW
. 453 BRB
. 640 RBE
====13====
. 231 WBW
. 450 BRE
. 645 RBR
PL/SQL 过程已成功完成。
已用时间: 00: 00: 00.20
TEST@orcl> EXEC cube_8.run_cube(3,3,'BWRBWRBER');
====0====
. 111 WWW
. 111 WWW
. 110 WWE
====1====
. 111 WWW
. 110 WWE
. 116 WWR
====2====
. 111 WWW
. 103 WEB
. 116 WWR
====3====
. 111 WWW
. 163 WRB
. 106 WER
====4====
. 111 WWW
. 163 WRB
. 036 EBR
====5====
. 111 WWW
. 063 ERB
. 636 RBR
====6====
. 011 EWW
. 663 RRB
. 636 RBR
====7====
. 301 BEW
. 663 RRB
. 636 RBR
====8====
. 311 BWW
. 603 REB
. 636 RBR
====9====
. 311 BWW
. 043 EBB
. 636 RBR
====10====
. 011 EWW
. 543 RBB
. 636 RBR
====11====
. 301 BEW
. 543 RBB
. 636 RBR
====12====
. 321 BWW
. 503 REB
. 636 RBR
====13====
. 321 BWW
. 553 RRB
. 606 RER
====14====
. 321 BWW
. 553 RRB
. 046 EBR
====15====
. 321 BWW
. 053 ERB
. 346 BBR
====16====
. 321 BWW
. 203 WEB
. 346 BBR
====17====
. 321 BWW
. 210 WWE
. 346 BBR
====18====
. 320 BWE
. 216 WWR
. 346 BBR
====19====
. 305 BER
. 216 WWR
. 346 BBR
====20====
. 015 EWR
. 216 WWR
. 346 BBR
====21====
. 415 BWR
. 016 EWR
. 346 BBR
====22====
. 415 BWR
. 306 BER
. 346 BBR
====23====
. 415 BWR
. 326 BWR
. 306 BER
PL/SQL 过程已成功完成。
已用时间: 00: 00: 11.01
TEST@orcl> EXEC cube_8.run_cube(2,1,'BBBBRBBRE');
BEGIN cube_8.run_cube(2,1,'BBBBRBBRE'); END;
*
第 1 行出现错误:
ORA-06500: PL/SQL: 存储错误
ORA-04030: 在尝试分配 16396 字节 (koh-kghu sessi,pmucalm coll) 时进程内存不足
ORA-06512: 在 "TEST.CUBE_8", line 44
ORA-06512: 在 "TEST.CUBE_8", line 76
ORA-06512: 在 "TEST.CUBE_8", line 85
ORA-06512: 在 "TEST.CUBE_8", line 120
ORA-06512: 在 line 1
已用时间: 00: 00: 40.21
TEST@orcl> EXEC cube_8.run_cube(1,1,'RRRWWWRRE');
BEGIN cube_8.run_cube(1,1,'RRRWWWRRE'); END;
*
第 1 行出现错误:
ORA-04030: 在尝试分配 4108 字节 (PLS non-lib hp,pdzfM60_Make) 时进程内存不足
已用时间: 00: 00: 00.00
TEST@orcl> EXEC cube_8.run_cube(2,1,'RRRBWBRRE');
BEGIN cube_8.run_cube(2,1,'RRRBWBRRE'); END;
*
第 1 行出现错误:
ORA-04030: 在尝试分配 4108 字节 (PLS non-lib hp,pdzfM60_Make) 时进程内存不足
已用时间: 00: 00: 00.00
TEST@orcl> EXEC cube_8.run_cube(3,2,'RRRWEWRRR');
BEGIN cube_8.run_cube(3,2,'RRRWEWRRR'); END;
*
第 1 行出现错误:
ORA-04030: 在尝试分配 4108 字节 (PLS non-lib hp,pdzfM60_Make) 时进程内存不足
已用时间: 00: 00: 00.01 |
|