|
你的前半截比我写得好,再次借用一下,嘻嘻。
with src as (select '73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450' xx from dual),
s as (select regexp_replace(xx,'[^0-9]','') x from src),
sp as (select substr(x,st+1,en-st-1) numgroup, st+1 st, en
from ( select decode(rn,1,0,instr(x,'0',1,rn-1)) st
,decode(instr(x,'0',1,rn),0,length(x)+1,instr(x,'0',1,rn)) en
from s, (select rownum rn from s connect by rownum<=length(x)-length(replace(x,'0',''))+1)
)
,s
where en>st+1 --过滤掉连续的0导致的空
),
sln as (
SELECT st pos,en-st len FROM (
select numgroup, st, en, sum(ln(to_number(substr(numgroup, rn, 1)))) sum_ln_num
from sp, (select rownum rn from (select max(en-st+1) maxlen from sp) connect by rownum<=maxlen)
where rn<=en-st group by numgroup, st, en
ORDER BY sum_ln_num DESC
)
WHERE ROWNUM=1
)
,t2 AS (
SELECT LEVEL n, TO_NUMBER(SUBSTR(x,pos+LEVEL-1,1)) val,pos,len
FROM sln
,s
CONNECT BY LEVEL<=len
)
,tmp AS
(SELECT *
FROM (SELECT n,col,prod,val,len,pos
FROM t2
,( SELECT ROWNUM col
-- 构造一个30 行的集合,这个集合的每一行用于存放30 位的临时计算结果
FROM DUAL
CONNECT BY ROWNUM<=30
) -- 上述两个集合做笛卡儿积,就为每个乘数n 分配了30 个col 作临时存放单元,
-- 最大可表示900 位的数字,用于存放对n 做阶乘的结果
MODEL IGNORE NAV RETURN UPDATED ROWS
DIMENSION BY (n,col) -- 用于定位到单元格的唯一标识
MEASURES (0 prod,val,len,pos ) -- prod 用于存放30 位的计算结果
RULES (
prod[any,any] order by n,col
-- MODEL 的规则指定n 从1~len,每个n 的col 从1~30 的顺序进行下列运算
=(CASE WHEN cv(n)=1 AND cv(col)=1 THEN val[1,1] -- 递归计算起点
ELSE MOD(prod[cv()-1,cv()],1E30)*val[cv(),1]
--取出在相同位置(col 相同)
--的计算结果的后30 位,乘以当前乘数val[cv(),1]
+TRUNC(prod[cv(),cv()-1]/1E30)
-- 再加上上一步乘法运算(位置col-1)的结果的进位部分
END)
)
)
WHERE n=len -- 在计算的结果中取出最后的那些单元格,用于拼接输出
)
SELECT SUBSTR(x,pos,len) str,pos,len,prod
FROM (SELECT MAX(pos) pos
,MAX(len) len
,LTRIM(REPLACE(MAX(SYS_CONNECT_BY_PATH(LPAD(MOD(prod,1E30),30,'0'),'*')),'*'),'0') as prod
FROM tmp
START WITH col=(SELECT MAX(col) FROM tmp WHERE prod>0)
CONNECT BY col = PRIOR col-1
)
,s
; |
|