楼主: newkid

[精华] ITPUB第2届“盛拓传媒杯”SQL数据库编程大赛第二期参考思路

[复制链接]
论坛徽章:
149
保时捷
日期:2013-09-17 13:41:40保时捷
日期:2013-10-23 11:01:24兰博基尼
日期:2013-09-17 13:41:40兰博基尼
日期:2013-10-31 13:54:31林肯
日期:2013-10-29 11:08:33林肯
日期:2013-09-17 13:41:40福特
日期:2013-09-17 13:41:40福特
日期:2013-10-24 14:12:53凯迪拉克
日期:2013-10-31 13:54:28凯迪拉克
日期:2013-09-17 13:41:40
21#
发表于 2013-11-25 10:47 | 只看该作者
真长姿势啊

使用道具 举报

回复
论坛徽章:
1
优秀写手
日期:2013-12-18 09:29:09
22#
发表于 2013-11-25 11:30 | 只看该作者
mark

使用道具 举报

回复
论坛徽章:
11
开发板块每日发贴之星
日期:2007-09-24 01:04:44开发板块每日发贴之星
日期:2010-07-29 01:01:01ERP板块每日发贴之星
日期:2010-07-29 01:01:01设计板块每日发贴之星
日期:2010-06-12 01:01:06ERP板块每日发贴之星
日期:2010-05-18 01:01:01数据库板块每日发贴之星
日期:2010-05-18 01:01:01设计板块每日发贴之星
日期:2008-10-16 01:03:26行业板块每日发贴之星
日期:2007-10-29 01:05:31ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-10-18 01:05:07
23#
发表于 2013-11-27 20:51 | 只看该作者
观摩中

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
24#
 楼主| 发表于 2013-11-30 05:50 | 只看该作者
用霹雳火pilisky的思路写出来的MODEL:迭代次数很少,利用前述四个推理规则搞定,只是前两行的顺序有些讲究。性能比上述写法都更好。

WITH cells AS (                      ------- 构造所有单元格及其坐标
   SELECT LEVEL cell_id              -------- 从左上角开始,从左到右从上到下从1开始编号
         ,CEIL(LEVEL/:v_width) r     -------- 行号,1~v_height
         ,MOD(LEVEL-1,:v_width)+1 c  -------- 列号,1~v_width
         ,SUBSTR(:v_str,LEVEL,1) cnt -------- 该单元格周围的地雷数目
     FROM DUAL CONNECT BY LEVEL<=:v_width*:v_height
)
,cells2 AS (
SELECT cell_id,r,c,DECODE(cnt,' ',0,TO_NUMBER(cnt)) AS cnt,MAX(CASE WHEN cell_id=1 THEN cnt END) OVER() AS cnt_1
       ------- 用CASE计算周围的空位数
      ,CASE WHEN cnt=' ' THEN 0
            ELSE CASE WHEN r>1 THEN
                      CASE WHEN c>1 THEN DECODE(SUBSTR(:v_str,cell_id-:v_width-1,1),' ',1,0) ELSE 0 END
                     +DECODE(SUBSTR(:v_str,cell_id-:v_width,1),' ',1,0)
                     +CASE WHEN c<:v_width THEN DECODE(SUBSTR(:v_str,cell_id-:v_width+1,1),' ',1,0) ELSE 0 END
                 ELSE 0
                 END
                +CASE WHEN c>1 THEN DECODE(SUBSTR(:v_str,cell_id-1,1),' ',1,0) ELSE 0 END
                +CASE WHEN c<:v_width THEN DECODE(SUBSTR(:v_str,cell_id+1,1),' ',1,0) ELSE 0 END
                +CASE WHEN r<:v_height THEN
                      CASE WHEN c>1 THEN DECODE(SUBSTR(:v_str,cell_id+:v_width-1,1),' ',1,0) ELSE 0 END
                     +DECODE(SUBSTR(:v_str,cell_id+:v_width,1),' ',1,0)
                     +CASE WHEN c<:v_width THEN DECODE(SUBSTR(:v_str,cell_id+:v_width+1,1),' ',1,0) ELSE 0 END
                 ELSE 0
                 END
       END AS empty_cnt
  from cells c1
)
,guess AS (SELECT 0 AS mine FROM DUAL UNION ALL SELECT 1 FROM DUAL)
,cells3 AS (
SELECT guess.mine AS solution_id
      ,cells2.cell_id
      ,cells2.r
      ,cells2.c
      ,cells2.cnt
      ,CASE WHEN cnt_1=' ' AND cnt>0 AND (r,c) IN ((1,2),(2,1),(2,2)) THEN cnt-guess.mine
            ELSE cells2.cnt
       END AS new_cnt
      ,CASE WHEN cnt_1=' ' AND (r,c) IN ((1,2),(2,1),(2,2)) THEN cells2.empty_cnt-1
            ELSE cells2.empty_cnt
       END AS empty_cnt
      ,CASE WHEN cells2.cell_id=1 AND cells2.cnt=0 THEN guess.mine ELSE -1 END AS guess_val
      ,COUNT(CASE WHEN cell_id>1 AND cnt=0 THEN 1 END) OVER(PARTITION BY guess.mine) AS empty_cells_cnt
  FROM cells2,guess
WHERE guess.mine=0 AND SUBSTR(:v_str,1,1)<>' ' OR SUBSTR(:v_str,1,1)=' '
)
,empty_cells AS (
  SELECT r,c,ROW_NUMBER() OVER(ORDER BY CASE WHEN cell_id<=2*:v_width THEN c ELSE 9999 END
                                       ,CASE WHEN cell_id<=2*:v_width THEN r ELSE 9999 END
                                       ,cell_id
                              ) empty_id
    FROM cells2
   WHERE cnt=0 AND cell_id>1  ---- 跳过(1,1)
)
,t AS (
SELECT * FROM cells3
MODEL
      REFERENCE e
         ON (SELECT * FROM empty_cells)
         DIMENSION BY (empty_id)
         MEASURES (r,c)
      MAIN m
      PARTITION BY (solution_id)
      DIMENSION BY (r,c)
      MEASURES (cnt,empty_cnt,new_cnt,guess_val,0 fail_flag,r r2, c c2,-1 tmp_val,empty_cells_cnt)
      RULES SEQUENTIAL ORDER
         ITERATE (10000) ----- 循环次数设为不可能达到的上限
         UNTIL (fail_flag[1,1]=1 OR ITERATION_NUMBER >=empty_cells_cnt[1,1])
         (
          r2[1,1] = e.r[ITERATION_NUMBER+1]
         ,c2[1,1] = e.c[ITERATION_NUMBER+1]
         ,tmp_val[1,1] = CASE WHEN cnt[r2[1,1]-1,c2[1,1]]=0 THEN
                                   guess_val[r2[1,1]-1,c2[1,1]]
                              WHEN cnt[r2[1,1]-1,c2[1,1]-1]>0 AND new_cnt[r2[1,1]-1,c2[1,1]-1] = 0 THEN 0
                              WHEN cnt[r2[1,1]-1,c2[1,1]-1]>0 AND new_cnt[r2[1,1]-1,c2[1,1]-1] = empty_cnt[r2[1,1]-1,c2[1,1]-1] THEN 1
                              ELSE -1
                         END
         ,guess_val[r2[1,1],c2[1,1]]=CASE WHEN tmp_val[1,1]=-1 OR guess_val[r2[1,1],c2[1,1]]=9 THEN guess_val[r2[1,1],c2[1,1]]
                                          WHEN guess_val[r2[1,1],c2[1,1]]<>-1 AND guess_val[r2[1,1],c2[1,1]]<>tmp_val[1,1] THEN 9
                                          ELSE tmp_val[1,1]
                                     END
         ,tmp_val[1,1] = CASE WHEN cnt[r2[1,1]-1,c2[1,1]]=0 THEN
                                   guess_val[r2[1,1]-1,c2[1,1]]
                              WHEN cnt[r2[1,1]-1,c2[1,1]]>0 AND new_cnt[r2[1,1]-1,c2[1,1]] = 0 THEN 0
                              WHEN cnt[r2[1,1]-1,c2[1,1]]>0 AND new_cnt[r2[1,1]-1,c2[1,1]] = empty_cnt[r2[1,1]-1,c2[1,1]] THEN 1
                              ELSE -1
                         END
         ,guess_val[r2[1,1],c2[1,1]]=CASE WHEN tmp_val[1,1]=-1 OR guess_val[r2[1,1],c2[1,1]]=9 THEN guess_val[r2[1,1],c2[1,1]]
                                          WHEN guess_val[r2[1,1],c2[1,1]]<>-1 AND guess_val[r2[1,1],c2[1,1]]<>tmp_val[1,1] THEN 9
                                          ELSE tmp_val[1,1]
                                     END
         ,tmp_val[1,1] = CASE WHEN cnt[r2[1,1],c2[1,1]-1]=0 THEN
                                   guess_val[r2[1,1],c2[1,1]-1]
                              WHEN cnt[r2[1,1],c2[1,1]-1]>0 AND new_cnt[r2[1,1],c2[1,1]-1] = 0 THEN 0
                              WHEN cnt[r2[1,1],c2[1,1]-1]>0 AND new_cnt[r2[1,1],c2[1,1]-1] = empty_cnt[r2[1,1],c2[1,1]-1] THEN 1
                              ELSE -1
                         END
         ,guess_val[r2[1,1],c2[1,1]]=CASE WHEN tmp_val[1,1]=-1 OR guess_val[r2[1,1],c2[1,1]]=9 THEN guess_val[r2[1,1],c2[1,1]]
                                          WHEN guess_val[r2[1,1],c2[1,1]]<>-1 AND guess_val[r2[1,1],c2[1,1]]<>tmp_val[1,1] THEN 9
                                          ELSE tmp_val[1,1]
                                     END
         ,tmp_val[1,1] = guess_val[r2[1,1],c2[1,1]]
         ,fail_flag[1,1]=CASE WHEN tmp_val[1,1]=-1 OR tmp_val[1,1]=9 THEN 1 ELSE 0 END
         ,new_cnt[r2[1,1]-1,c2[1,1]-1]  = new_cnt[r2[1,1]-1,c2[1,1]-1] - tmp_val[1,1]
         ,new_cnt[r2[1,1]-1,c2[1,1]  ]  = new_cnt[r2[1,1]-1,c2[1,1]  ] - tmp_val[1,1]
         ,new_cnt[r2[1,1]-1,c2[1,1]+1]  = new_cnt[r2[1,1]-1,c2[1,1]+1] - tmp_val[1,1]
         ,new_cnt[r2[1,1]  ,c2[1,1]-1]  = new_cnt[r2[1,1]  ,c2[1,1]-1] - tmp_val[1,1]
         ,new_cnt[r2[1,1]  ,c2[1,1]+1]  = new_cnt[r2[1,1]  ,c2[1,1]+1] - tmp_val[1,1]
         ,new_cnt[r2[1,1]+1,c2[1,1]-1]  = new_cnt[r2[1,1]+1,c2[1,1]-1] - tmp_val[1,1]
         ,new_cnt[r2[1,1]+1,c2[1,1]  ]  = new_cnt[r2[1,1]+1,c2[1,1]  ] - tmp_val[1,1]
         ,new_cnt[r2[1,1]+1,c2[1,1]+1]  = new_cnt[r2[1,1]+1,c2[1,1]+1] - tmp_val[1,1]
         ,empty_cnt[r2[1,1]-1,c2[1,1]-1]= empty_cnt[r2[1,1]-1,c2[1,1]-1] - 1         
         ,empty_cnt[r2[1,1]-1,c2[1,1]  ]= empty_cnt[r2[1,1]-1,c2[1,1]  ] - 1         
         ,empty_cnt[r2[1,1]-1,c2[1,1]+1]= empty_cnt[r2[1,1]-1,c2[1,1]+1] - 1         
         ,empty_cnt[r2[1,1]  ,c2[1,1]-1]= empty_cnt[r2[1,1]  ,c2[1,1]-1] - 1         
         ,empty_cnt[r2[1,1]  ,c2[1,1]+1]= empty_cnt[r2[1,1]  ,c2[1,1]+1] - 1         
         ,empty_cnt[r2[1,1]+1,c2[1,1]-1]= empty_cnt[r2[1,1]+1,c2[1,1]-1] - 1         
         ,empty_cnt[r2[1,1]+1,c2[1,1]  ]= empty_cnt[r2[1,1]+1,c2[1,1]  ] - 1         
         ,empty_cnt[r2[1,1]+1,c2[1,1]+1]= empty_cnt[r2[1,1]+1,c2[1,1]+1] - 1         
         )
)
SELECT res
  FROM (
SELECT LISTAGG(CASE WHEN cnt=0 THEN CASE WHEN guess_val=1 THEN '*' ELSE ' ' END ELSE TO_CHAR(cnt) END) WITHIN GROUP (ORDER BY r,c) as res
FROM (
SELECT t.*,MAX(fail_flag) OVER(PARTITION BY solution_id) fail
      ,SUM(CASE WHEN cnt=0 THEN guess_val END) OVER(PARTITION BY solution_id) mine_cnt
  FROM t
WHERE cnt IS NOT NULL
)
WHERE fail=0 AND mine_cnt=:v_cnt
GROUP BY solution_id
)
WHERE ROWNUM=1
;

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
25#
 楼主| 发表于 2013-11-30 10:45 | 只看该作者
本帖最后由 newkid 于 2013-12-4 06:40 编辑

最基本的递归法,只是前两行排序了一下改为一上一下,性能马上就追上了泼墨递归法:(注意empty_cells子查询里面的ORDER BY)

WITH cells AS (                      ------- 构造所有单元格及其坐标
   SELECT LEVEL cell_id              -------- 从左上角开始,从左到右从上到下从1开始编号
         ,CEIL(LEVEL/:v_width) r     -------- 行号,1~v_height
         ,MOD(LEVEL-1,:v_width)+1 c  -------- 列号,1~v_width
         ,SUBSTR(:v_str,LEVEL,1) cnt -------- 该单元格周围的地雷数目
     FROM DUAL CONNECT BY LEVEL<=:v_width*:v_height
)
,cells2 AS (
SELECT cell_id,r,c,DECODE(cnt,' ',0,TO_NUMBER(cnt)) AS cnt
       ------ 如果每个方位的邻居不存在,比如边界上,把该邻居的id设为大数999999, 这样SUBSTR不报错只是返回NULL
      ,CASE WHEN r>1 AND c>1         THEN cell_id-:v_width-1 ELSE 999999 END AS n1  ---- 左上方邻居的id
      ,CASE WHEN r>1                 THEN cell_id-:v_width   ELSE 999999 END AS n2  ---- 正上方邻居的id
      ,CASE WHEN r>1 AND c<:v_width  THEN cell_id-:v_width+1 ELSE 999999 END AS n3  ---- 右上方邻居的id
      ,CASE WHEN c>1                 THEN cell_id-1          ELSE 999999 END AS n4  ---- 左边邻居的id
      ,CASE WHEN c<:v_width          THEN cell_id+1          ELSE 999999 END AS n5  ---- 右边邻居的id
      ,CASE WHEN r<:v_height AND c>1 THEN cell_id+:v_width-1 ELSE 999999 END AS n6  ---- 左下方邻居的id
      ,CASE WHEN r<:v_height         THEN cell_id+:v_width   ELSE 999999 END AS n7  ---- 正下方邻居的id
      ,CASE WHEN r<:v_height AND c<:v_width THEN cell_id+:v_width+1 ELSE 999999 END AS n8  ---- 右下方邻居的id
      ,(SELECT COUNT(*)  ---- 用COUNT计算周围的空位数
          FROM cells c2
         WHERE c1.cell_id<>c2.cell_id AND c2.cnt=' ' AND ABS(c1.r-c2.r)<=1 AND ABS(c1.c-c2.c)<=1) AS empty_cnt
  from cells c1
)
,empty_cells AS (
SELECT  --------- 找出所有空位及其邻居位置, 空位是未标数字的单元格,可能有地雷也可能没有               
       cc.*
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n1,1))),0) cnt1 ---- 邻居的数字标号。空位或不存在的邻居(边界)则为0
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n2,1))),0) cnt2
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n3,1))),0) cnt3
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n4,1))),0) cnt4
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n5,1))),0) cnt5
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n6,1))),0) cnt6
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n7,1))),0) cnt7
      ,NVL(TO_NUMBER(TRIM(SUBSTR(:v_str,n8,1))),0) cnt8
      ,ROWNUM empty_id ---------- 按顺序为空位取编号,递归的时候每层编号递增,按序猜测每个空位
  FROM (SELECT * FROM cells2
         WHERE cnt=0          ------- 空位
        ORDER BY CASE WHEN cell_id<=2*:v_width THEN c ELSE 9999 END  -------------- 霹雳火思路
                          ,CASE WHEN cell_id<=2*:v_width THEN r ELSE 9999 END
                          ,cell_id
       ) cc
)
,guess AS (SELECT 0 AS mine FROM DUAL UNION ALL SELECT 1 FROM DUAL)
,t(cnt_str   ---- 所有格子的计数器, 合并为一个字符串。当猜测为地雷时,就把周围8个计数器都减1
  ,m_cnt     ---- 到目前为止猜测为地雷的总数, 达到:V_CNT时就结束
  ,empty_id  ---- 目前要猜测哪个空位
  ,res       ---- 最后输出的结果。每猜出一个雷就拼一个 * 进去
  ,empty_cnt_str ---- 每个格子周围的空位计数器,即未猜测的格子数。每结束一个空位的猜测,周围的8个计数器都减1
  ) AS (
SELECT CAST(:v_str AS VARCHAR2(1000))  -------- 计数器初始化
      ,0   ------- 未猜测之前总雷数为0   
      ,1   ------- 从第一个空位开始遍历
      ,CAST(:v_str AS VARCHAR2(1000))  -------- 输出初始为原分布,在递归过程中嵌入地雷
      ,CAST(LISTAGG(CASE WHEN cnt>0 THEN TO_CHAR(empty_cnt) ELSE ' ' END)  ---- 把所有空位计数器合并为一个字符串, 标有数字的才计数
        WITHIN GROUP (ORDER BY cell_id) AS VARCHAR2(1000))
  FROM cells2
WHERE NOT EXISTS (SELECT 1 FROM cells2 WHERE cnt>empty_cnt) ---如果数字比周围的空位还多,说明题目有错,显然无解
UNION ALL
SELECT CASE WHEN guess.mine=0 THEN cnt_str---- 如果当前猜无雷,则计数器保持原样
       ELSE (SELECT LISTAGG  -------- 如果猜有雷,把计数器cnt_str打散后修改再串起来
                   (CASE WHEN LEVEL IN (e.n1,e.n2,e.n3,e.n4,e.n5,e.n6,e.n7,e.n8)     --------- 如果是邻居
                              AND SUBSTR(:v_str,LEVEL,1)<>' '       --------- 而且不是空位
                              THEN TO_CHAR(NVL(TRIM(SUBSTR(cnt_str,LEVEL,1)),0)-1)    --------- 对计数器进行修改
                         ELSE SUBSTR(cnt_str,LEVEL,1)               --------- 非邻居, 或者是空位的不用修改
                    END) WITHIN GROUP (ORDER BY LEVEL)
               FROM DUAL
              CONNECT BY LEVEL<=LENGTH(cnt_str)  ---- 用CONNECT BY和SUBSTR打散字符串cnt_str
            )
       END AS cnt_str
      ,m_cnt + guess.mine ---- 总雷数递增或不变,取决于当前猜测
      ,t.empty_id+1  ------- 空单元格编号推进
      ,SUBSTR(res,1,cell_id-1)||CASE WHEN guess.mine=1 THEN '*' ELSE ' ' END||SUBSTR(res,cell_id+1) ---在输出结果中嵌入地雷
      ,(SELECT LISTAGG  -------- 把空位计数器empty_cnt_str打散后修改再串起来
                   (CASE WHEN LEVEL IN (e.n1,e.n2,e.n3,e.n4,e.n5,e.n6,e.n7,e.n8)     --------- 如果是邻居
                              AND SUBSTR(:v_str,LEVEL,1)<>' '       --------- 而且不是空位
                              THEN TO_CHAR(NVL(TRIM(SUBSTR(t.empty_cnt_str,LEVEL,1)),0)-1)    --------- 对空位计数器进行修改
                         ELSE SUBSTR(t.empty_cnt_str,LEVEL,1)         --------- 非邻居, 或者邻居是空位的不用修改
                    END) WITHIN GROUP (ORDER BY LEVEL)
               FROM DUAL
              CONNECT BY LEVEL<=LENGTH(t.empty_cnt_str) ---- 用CONNECT BY和SUBSTR打散字符串empty_cnt_str
       )
  FROM t
      ,empty_cells e
      ,guess  ---和两种猜测做笛卡尔积:0:没有地雷,1:有地雷
WHERE t.empty_id<=(SELECT MAX(empty_id) FROM empty_cells)   ------- 空位编号推进直至最大
       AND t.empty_id=e.empty_id   ------连接到empty_cells表,取当前猜测空位的坐标、邻居等信息
       AND  t.m_cnt<:v_cnt  ---- 总雷数不能溢出
       AND  CASE WHEN SUBSTR(t.res,e.n1,1)=' ' OR SUBSTR(t.cnt_str,e.n1,1)='0' THEN 0  ---- 如果邻居已经被猜为无雷,或者计数器已经饱和,必须猜0
                 ------- 如果邻居剩下未猜格子数等于未分配地雷数,必须猜1                    
                 WHEN SUBSTR(t.res,e.n1,1)='*' OR e.cnt1>0 AND SUBSTR(t.empty_cnt_str,e.n1,1)=SUBSTR(t.cnt_str,e.n1,1) THEN 1
                 ELSE guess.mine ---- 否则不限
            END=guess.mine
       AND  CASE WHEN SUBSTR(t.res,e.n2,1)=' ' OR SUBSTR(t.cnt_str,e.n2,1)='0' THEN 0 -------邻居2-8的规则同邻居1
                 WHEN SUBSTR(t.res,e.n2,1)='*' OR e.cnt2>0 AND SUBSTR(t.empty_cnt_str,e.n2,1)=SUBSTR(t.cnt_str,e.n2,1) THEN 1
                 ELSE guess.mine
            END=guess.mine
       AND  CASE WHEN SUBSTR(t.cnt_str,e.n3,1)='0' THEN 0  
                 WHEN e.cnt3>0 AND SUBSTR(t.empty_cnt_str,e.n3,1)=SUBSTR(t.cnt_str,e.n3,1) THEN 1
                 ELSE guess.mine
            END=guess.mine
       AND  CASE WHEN SUBSTR(t.res,e.n4,1)=' ' OR SUBSTR(t.cnt_str,e.n4,1)='0' THEN 0  
                 WHEN SUBSTR(t.res,e.n4,1)='*' OR e.cnt4>0 AND SUBSTR(t.empty_cnt_str,e.n4,1)=SUBSTR(t.cnt_str,e.n4,1) THEN 1
                 ELSE guess.mine
            END=guess.mine
       AND  CASE WHEN SUBSTR(t.cnt_str,e.n5,1)='0' THEN 0  ---- 从5号邻居开始为未猜测,去掉前两个规则的判断
                 WHEN e.cnt5>0 AND SUBSTR(t.empty_cnt_str,e.n5,1)=SUBSTR(t.cnt_str,e.n5,1) THEN 1
                 ELSE guess.mine
            END=guess.mine
       AND  CASE WHEN SUBSTR(t.cnt_str,e.n6,1)='0' THEN 0  
                 WHEN e.cnt6>0 AND SUBSTR(t.empty_cnt_str,e.n6,1)=SUBSTR(t.cnt_str,e.n6,1) THEN 1
                 ELSE guess.mine
            END=guess.mine
       AND  CASE WHEN SUBSTR(t.cnt_str,e.n7,1)='0' THEN 0
                 WHEN e.cnt7>0 AND SUBSTR(t.empty_cnt_str,e.n7,1)=SUBSTR(t.cnt_str,e.n7,1) THEN 1
                 ELSE guess.mine
            END=guess.mine
       AND  CASE WHEN SUBSTR(t.cnt_str,e.n8,1)='0' THEN 0
                 WHEN e.cnt8>0 AND SUBSTR(t.empty_cnt_str,e.n8,1)=SUBSTR(t.cnt_str,e.n8,1) THEN 1
                 ELSE guess.mine
            END=guess.mine
)
SELECT res
FROM t
WHERE m_cnt=:v_cnt ---------- 总雷数必须符合
       AND cnt_str=TRANSLATE(:v_str,'12345678','00000000') ------ 正确的猜测结果,应该所有的计数器都为零
       AND ROWNUM=1  ---------- 有多种答案的话只选任一种
;

挖空心思去合并空位都是白费劲!霹雳哥真乃神人也!

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
26#
发表于 2013-11-30 12:44 | 只看该作者
25楼和model比还是很慢
set lines 120 pages 50000
set head on
set num 5
select * from
(select id,qid,score from dlfj_time )
pivot(min(score) for qid in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,100))order by 0+id;

ID             1     2     3     4     5     6     7     8     9    10    11    12    13    14    15   100
---------- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
100          .08   .14   .01   .01   .01   .01   .31   .33     0   .02   .12   .46   .89   .76   .11  7.17
121          .07   .08     0   .01   .01   .01   .19   .28   .23   .05   .36  1.05   .05   .05   .02  11.9
133          .08   .05   .01   .01   .01   .01   .07   .11   .07   .12   .26   .23   .27   .12   .01 20.33
134          .06   .03   .01   .01   .01   .01     2  9.36   .06   .14   .66 18.44 22.08 11.84   .01

使用道具 举报

回复
论坛徽章:
737
季节之章:春
日期:2015-07-31 17:16:29ITPUB季度 技术新星
日期:2014-07-17 14:37:00季节之章:秋
日期:2015-07-31 17:16:14季节之章:夏
日期:2015-07-31 17:16:29股神
日期:2014-10-15 09:23:31衰神
日期:2014-10-20 22:47:12季节之章:冬
日期:2015-07-31 17:16:14红钻
日期:2014-12-16 17:51:41洛杉矶湖人
日期:2016-09-23 08:18:15布鲁克林篮网
日期:2016-09-23 08:17:18
27#
发表于 2013-11-30 12:51 | 只看该作者
model好高级,准备集中时间学下

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
28#
发表于 2013-11-30 12:52 | 只看该作者
11.2.0.4上25楼的结果
134          .11   .11   .01   .02   .02   .01   .08   .01  2.24   .16  1.06 11.68 15.93 10.48  6.22 74.74

使用道具 举报

回复
论坛徽章:
20
SQL大赛参与纪念
日期:2013-12-06 14:03:45生肖徽章:狗
日期:2013-12-09 14:28:47生肖徽章:猪
日期:2013-12-09 14:28:472009架构师大会纪念徽章
日期:2015-08-03 13:54:362010系统架构师大会纪念
日期:2015-08-03 13:54:362011系统架构师大会纪念章
日期:2015-08-03 13:54:362012系统架构师大会纪念章
日期:2015-08-03 13:54:362013系统架构师大会纪念章
日期:2015-08-03 13:54:362014系统架构师大会纪念章
日期:2015-08-03 13:54:36生肖徽章:鸡
日期:2013-12-09 14:28:47
29#
发表于 2013-11-30 17:13 | 只看该作者
大师就是大师,慢慢消化

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
30#
 楼主| 发表于 2013-12-1 10:35 | 只看该作者
〇〇 发表于 2013-11-30 12:44
25楼和model比还是很慢
set lines 120 pages 50000
set head on

你发这些数据很难看懂,必须说明一下每个ID到底代表着什么。
下周我再把丑陋递归法重新改一下,看看有没有提高。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表