楼主: rollingpig

优化过的我的复活节答案

[复制链接]
招聘 : 数据库管理员
论坛徽章:
9
生肖徽章2007版:牛
日期:2009-03-10 21:26:492010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:葡萄牙
日期:2010-02-22 14:35:242010新春纪念徽章
日期:2010-03-01 11:19:092010广州亚运会纪念徽章:射击
日期:2010-09-08 23:42:12ITPUB9周年纪念徽章
日期:2010-10-08 09:31:212010广州亚运会纪念徽章:拳击
日期:2010-10-30 00:46:582011新春纪念徽章
日期:2011-02-18 11:43:322011新春纪念徽章
日期:2011-03-01 08:49:39
11#
发表于 2011-5-4 16:56 | 只看该作者
下一个是不是风干版 ^_^

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
12#
 楼主| 发表于 2011-5-4 17:08 | 只看该作者
所有的if都可以不加括号

现在是1140了


  1. CREATE OR REPLACE PACKAGE BODY EASTER is
  2.   -- Point 0: 1个table保存N种数据
  3.   -- 数据1. 某一年对应的dateindex
  4.   -- dateindex计算方式
  5.   -- 20 for 3/21
  6.   -- 3月
  7.   -- 日期 - 1
  8.   -- 3/22 = 21
  9.   -- 3/31 = 30
  10.   -- 四月
  11.   -- 日期 + 30
  12.   -- 4/1 = 1+30 = 31
  13.   -- 4/25 = 25+30 = 55
  14.   -- 数据2. 日期重复数,保存为负数
  15.   -- 数据3. 日期对应的("MM-DD") 输出,索引为-dateindex
  16.   -- 数据4. 通过ceil(dateindex/30), 分别用s(1)代表3月份,s(2)代表4月份重复数,同时记为负数,参考nyfor
  17.   -- Point 1: 用 dbms_sql.varchar2s 代替 dbms_sql.number_table
  18. S dbms_sql.varchar2s;
  19. -- Point 2: 用 subtype, 参考某人,具体忘了,不好意思
  20. subtype v is varchar(999);
  21. -- Point 3: 共享的local 变量,多次使用
  22. N v;
  23. m v;
  24. -- Point 4: Function o, 代替 dbms_output.put_line,用两个变量,避免其他地方大量的||' '||操作符
  25. procedure o(l v,k v:='') as
  26. begin
  27.   dbms_output.put_line(l||' '||k);
  28.   --Package初始化,放在这里省一个begin,参考nyfor
  29.   --begin
  30.   for i in 1..61 loop
  31.     s(i):=0;
  32.     --用date'1-3-1' 代替to_date(...),参考某人,具体忘了,不好意思
  33.     s(-i):=to_char(date'1-3-1'+i,'MM-DD');
  34.   end loop;
  35.   -- Caculate EASTER date for certain year(1900-2099)
  36.   -- Return a date interval compare to 3/31
  37.   -- Return 1 for 3/22, 11 for 4/1 etc.
  38.   -- Point 6,combine the expression
  39.   --Reuse M/N
  40.   --N int;
  41.   --Q int;
  42.   --B int;
  43.   --M int;
  44.   --W int;
  45.   for Y in 2011..2099 loop
  46.     --N:=Y-1900;
  47.     --A:=mod(N,19);
  48.     --Q:=floor(N/4);
  49.     --B:=floor((7*mod(N,19)+1)/19);
  50.     --M:=mod(11*A+4-B,29);
  51.     -- a mod b 代替 mod(a,b), 参考某人,具体忘了,不好意思
  52.     N:=Y mod 19;
  53.     N:=(11*N+4-floor((7*N+1)/19)) mod 29;
  54.     --W:=mod(N+floor(N/4)+31-M,7);
  55.     --return 25-M-W;
  56.     -- -2344 =  -1900-1900/4+31 , 参考nyfor
  57.     N:=55-N-(Y-6+floor(Y/4)-N) mod 7;
  58.     s(Y):=N;
  59.     -- Previos count in the EASTER date+1
  60.     -- o(s(n));
  61.     s(N):=s(N)-1;
  62.     --用上下标代替if/else, 参考nyfor
  63.     M:=ceil(N/30);
  64.     s(M):=least(+s(M),s(N));
  65.   end loop;
  66.   --把临时变量设为null
  67.   N:='';
  68. end;
  69. procedure showAllEasterDay as
  70. begin               
  71.   --Header
  72.   o('YEAR DAY');
  73.   for Y in 2011..2099 loop
  74.     o(Y,s(-s(y)));
  75.   end loop;
  76. end;
  77. -- 最大重复数
  78. procedure showMaxOccurenceEasterDay as
  79.   procedure u(x v,y v,z v:=55) as
  80.   begin
  81.     for i in y..z loop
  82.       if s(i)=x then
  83.         N:=N||s(-i)||'/' ;
  84.       end if;
  85.     end loop;
  86.     --c:=replace(c||x,'/-',' ')||'       ';
  87.     N:=rtrim(N,'/')||' '||-x||'       ';
  88.     --c:=substr(c,2)||' '||-x||' ';
  89.   end;
  90. begin
  91.   o('MAXOCC                                    MO_CNT  MAXOCC_3    MO3_CNT MAXOCC_4                      MO4_CNT');
  92.   -- 所有最大重复
  93.   u(least(+s(1),s(2)),9);
  94.   --3月最大重复   
  95.   u(s(1),9,30);
  96.   --4月最大重复
  97.   u(s(2),31);
  98.   --输出
  99.   o(N);
  100. end;
  101. procedure showLeapEasterDay as
  102. begin
  103.   --Header
  104.   o('ABSENT_START ABSENT_END');
  105.   --ABSENT Begin data
  106.   --21=22-1 = 3/22, 55=25+30 = 4/25
  107.   for i in 21..55 loop
  108.     --   o(s(i)||' '||s(-i));
  109.     if s(i)=0 then
  110.       --Start of ABSENT
  111.       N:=nvl(N,i);
  112.     end if;
  113.     -- 合并判断,参考nyfor
  114.     --Point 10: N>0 to replace "N is not null"
  115.     if  i = 55 + N - N or s(i + 1) < N - N  then
  116.       o(s(-N),s(-i));
  117.       --start over,N set to null
  118.       -- N:='';
  119.     end if;
  120.   end loop;
  121. end;
  122. --show Fool Easter Day
  123. procedure showFoolEasterDay as
  124. begin
  125.   -- Caculate Occurence Easter Day
  126.   --Header
  127.   o('YEAR TOTAL');
  128.   for Y in 2011..2099 loop
  129.     -- if F(Y)=4/1,output,get total cnt from S(31),31=30+1
  130.     if s(Y)=31 then
  131.       -- Ponit 11, get total April-1 count from pre-caculated Occurence Easter Day:S.
  132.       o (Y,-s(31));
  133.     end if;
  134.   end loop;
  135. end;
  136. end;
  137. /
复制代码

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
13#
 楼主| 发表于 2011-5-4 17:34 | 只看该作者
还可以进一步。
1. dbms_sql.varchar2s 有可替代的吗?
select NAME,text from dba_source
where upper(text) like '%TABLE%VARCHAR%INDEX%'   
order by length(NAME)

OWA    type nc_arr is table of nvarchar2(16000) index by binary_integer;

用 OWA.vc_arr 又省8个字节

2. subtype varchar(999) 有可替代的吗?

select NAME,text from dba_source
where upper(text) like '%SUBTYPE%CHAR%'   
order by length(NAME)

LONG/RAW/ROWID 都无法进行隐式转换至 number, string可以。

subtype v is STRING(999);
省一个。
最终1131


  1. CREATE OR REPLACE PACKAGE BODY EASTER is
  2.   -- Point 0: 1个table保存N种数据
  3.   -- 数据1. 某一年对应的dateindex
  4.   -- dateindex计算方式
  5.   -- 20 for 3/21
  6.   -- 3月
  7.   -- 日期 - 1
  8.   -- 3/22 = 21
  9.   -- 3/31 = 30
  10.   -- 四月
  11.   -- 日期 + 30
  12.   -- 4/1 = 1+30 = 31
  13.   -- 4/25 = 25+30 = 55
  14.   -- 数据2. 日期重复数,保存为负数
  15.   -- 数据3. 日期对应的("MM-DD") 输出,索引为-dateindex
  16.   -- 数据4. 通过ceil(dateindex/30), 分别用s(1)代表3月份,s(2)代表4月份重复数,同时记为负数,参考nyfor
  17.   -- Point 1: 用 dbms_sql.varchar2s 代替 dbms_sql.number_table
  18. --S utl_http.vc2_table;
  19. --S dbms_sql.varchar2s;
  20. --S htp.htbuf_arr;
  21. S OWA.vc_arr;
  22. -- Point 2: 用 subtype, 参考某人,具体忘了,不好意思
  23. subtype v is STRING(999);
  24. --subtype v is VARCHAR(999);
  25. -- Point 3: 共享的local 变量,多次使用
  26. N v;
  27. m v;
  28. -- Point 4: Function o, 代替 dbms_output.put_line,用两个变量,避免其他地方大量的||' '||操作符
  29. procedure o(l v,k v:='') as
  30. begin
  31.   dbms_output.put_line(l||' '||k);
  32.   --Package初始化,放在这里省一个begin,参考nyfor
  33.   --begin
  34.   for i in 1..61 loop
  35.     s(i):=0;
  36.     --用date'1-3-1' 代替to_date(...),参考某人,具体忘了,不好意思
  37.     s(-i):=to_char(date'1-3-1'+i,'MM-DD');
  38.   end loop;
  39.   -- Caculate EASTER date for certain year(1900-2099)
  40.   -- Return a date interval compare to 3/31
  41.   -- Return 1 for 3/22, 11 for 4/1 etc.
  42.   -- Point 6,combine the expression
  43.   --Reuse M/N
  44.   --N int;
  45.   --Q int;
  46.   --B int;
  47.   --M int;
  48.   --W int;
  49.   for Y in 2011..2099 loop
  50.     --N:=Y-1900;
  51.     --A:=mod(N,19);
  52.     --Q:=floor(N/4);
  53.     --B:=floor((7*mod(N,19)+1)/19);
  54.     --M:=mod(11*A+4-B,29);
  55.     -- a mod b 代替 mod(a,b), 参考某人,具体忘了,不好意思
  56.     N:=Y mod 19;
  57.     N:=(11*N+4-floor((7*N+1)/19)) mod 29;
  58.     --W:=mod(N+floor(N/4)+31-M,7);
  59.     --return 25-M-W;
  60.     -- -2344 =  -1900-1900/4+31 , 参考nyfor
  61.     N:=55-N-(Y-6+floor(Y/4)-N) mod 7;
  62.     s(Y):=N;
  63.     -- Previos count in the EASTER date+1
  64.     -- o(s(n));
  65.     s(N):=s(N)-1;
  66.     --用上下标代替if/else, 参考nyfor
  67.     M:=ceil(N/30);
  68.     s(M):=least(+s(M),s(N));
  69.   end loop;
  70.   --把临时变量设为null
  71.   N:='';
  72. end;
  73. procedure showAllEasterDay as
  74. begin               
  75.   --Header
  76.   o('YEAR DAY');
  77.   for Y in 2011..2099 loop
  78.     o(Y,s(-s(y)));
  79.   end loop;
  80. end;
  81. -- 最大重复数
  82. procedure showMaxOccurenceEasterDay as
  83.   procedure u(x v,y v,z v:=55) as
  84.   begin
  85.     for i in y..z loop
  86.       if s(i)=x then
  87.         N:=N||s(-i)||'/' ;
  88.       end if;
  89.     end loop;
  90.     --c:=replace(c||x,'/-',' ')||'       ';
  91.     N:=rtrim(N,'/')||' '||-x||'       ';
  92.     --c:=substr(c,2)||' '||-x||' ';
  93.   end;
  94. begin
  95.   o('MAXOCC                                    MO_CNT  MAXOCC_3    MO3_CNT MAXOCC_4                      MO4_CNT');
  96.   -- 所有最大重复
  97.   u(least(+s(1),s(2)),9);
  98.   --3月最大重复   
  99.   u(s(1),9,30);
  100.   --4月最大重复
  101.   u(s(2),31);
  102.   --输出
  103.   o(N);
  104. end;
  105. procedure showLeapEasterDay as
  106. begin
  107.   --Header
  108.   o('ABSENT_START ABSENT_END');
  109.   --ABSENT Begin data
  110.   --21=22-1 = 3/22, 55=25+30 = 4/25
  111.   for i in 21..55 loop
  112.     --   o(s(i)||' '||s(-i));
  113.     if s(i)=0 then
  114.       --Start of ABSENT
  115.       N:=nvl(N,i);
  116.     end if;
  117.     -- 合并判断,参考nyfor
  118.     --Point 10: N>0 to replace "N is not null"
  119.     if  i = 55 + N - N or s(i + 1) < N - N  then
  120.       o(s(-N),s(-i));
  121.       --start over,N set to null
  122.       -- N:='';
  123.     end if;
  124.   end loop;
  125. end;
  126. --show Fool Easter Day
  127. procedure showFoolEasterDay as
  128. begin
  129.   -- Caculate Occurence Easter Day
  130.   --Header
  131.   o('YEAR TOTAL');
  132.   for Y in 2011..2099 loop
  133.     -- if F(Y)=4/1,output,get total cnt from S(31),31=30+1
  134.     if s(Y)=31 then
  135.       -- Ponit 11, get total April-1 count from pre-caculated Occurence Easter Day:S.
  136.       o (Y,-s(31));
  137.     end if;
  138.   end loop;
  139. end;
  140. end;
  141. /

复制代码

使用道具 举报

回复
论坛徽章:
69
生肖徽章2007版:羊
日期:2008-11-14 14:42:19复活蛋
日期:2011-08-06 08:59:05ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20版主4段
日期:2012-05-15 15:24:11
14#
发表于 2011-5-4 17:44 | 只看该作者
RollingPig, 你太牛了!

使用道具 举报

回复
论坛徽章:
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
15#
发表于 2011-5-4 19:42 | 只看该作者
我有一个想法,用一个超长字符串,里面装上很多空格,tab,cr等然后这些都不会记入长度,就可以在上面做很多文章

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期: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
16#
发表于 2011-5-4 21:46 | 只看该作者
原帖由 〇〇 于 2011-5-4 19:42 发表
我有一个想法,用一个超长字符串,里面装上很多空格,tab,cr等然后这些都不会记入长度,就可以在上面做很多文章

怎么做?你这些空白符没办法变成代码呀。
野花的奖品呢?

使用道具 举报

回复
论坛徽章:
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
17#
发表于 2011-5-4 22:04 | 只看该作者
类似下面的,用长度保存ascii码

set serverout on
declare
x varchar(32767):='

              ';
n number:=0;
begin
for i in 1..length(x)loop
for j in 1..128 loop
if substr(x,j+n,1)=' ' then
n:=n+1;
else
continue;
end if;
end loop;
dbms_output.put(chr(n));
end loop;
dbms_output.put_line('');
end;
/

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期: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
18#
发表于 2011-5-4 22:12 | 只看该作者
解码部分太复杂,得不偿失。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
19#
发表于 2011-5-4 22:42 | 只看该作者
原帖由 〇〇 于 11-5-4 16:23 发表
最浪费长度的过程名,除了用动态plsql无法缩短


我觉得这点上你们要感谢我
要是我用一个字母来指定这些过程名呢? 嘿嘿
多加几个过程,再多加几个参数,哼哼,那你们的代码就只会变长而不是变短了

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
20#
发表于 2011-5-4 22:43 | 只看该作者
原帖由 newkid 于 11-5-4 21:46 发表

怎么做?你这些空白符没办法变成代码呀。
野花的奖品呢?


这礼拜肯定能发出啦~别着急~~

使用道具 举报

回复

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

本版积分规则 发表回复

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