楼主: nyfor

[精华] nyfor 复活节比短代码解题说明

[复制链接]
论坛徽章:
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
31#
 楼主| 发表于 2011-4-28 21:18 | 只看该作者
原帖由 jboracle1981 于 2011-4-28 19:36 发表
牛!
老大,干脆把这个
subtype w is varchar(999)
改成
subtype w is long算了吧,虽然意义不大。
土点就土点,应该不会出错吧
突破2000b

呵呵,要突破1200bytes,也不用这么变态且不能编译的方法。
将 substr(c(y),-2) = 1 这个条件改为 c(y) like '%01' 即可立减 4 bytes

最终为 1196 bytes
create or replace package easter is
  procedure showAllEasterDay;
  procedure showMaxOccurenceEasterDay;
  procedure showLeapEasterDay;
  procedure showFoolEasterDay;
end;
/
create or replace package body easter is
  c dbms_sql.varchar2s;
  subtype w is varchar(999);

  s w;
  x w;
  v date := date '1-3-31';

  procedure p(t w) is
  begin
    dbms_output.put_line(t);

    for i in -30 .. 50 loop
      c(i) := 0;
    end loop;

    for y in 2011 .. 2099 loop
      s := y mod 19;
      s := (11 * s + 4 - trunc((7 * s + 1) / 19)) mod 29;
      x := 25 - s - (y - 2344 + trunc(y / 4) - s) mod 7;

      c(y) := to_char(v + x, ' mm-dd');

      c(x) := c(x) - 1;

      s := sign(x - 1) + 40;
      c(s) := least(+c(x), c(s));
    end loop;
    s := '';
  end;

  procedure showAllEasterDay is
  begin
    p('YEAR DAY');
    for y in 2011 .. 2099 loop
      p(y || c(y));
    end loop;
  end;
  procedure z(w w, n w := 30, m w := -30) is
  begin
    for f in m .. n loop
      if c(f) = w then
        s := s || to_char(v + f, 'mm-dd/');
      end if;
    end loop;
    s := rtrim(s, '/') || ' ' || -w || ' ';
  end;
  procedure showMaxOccurenceEasterDay is
  begin
    p('MAXOCC                               MO_CNT MAXOCC_3 MO3_CNT    MAXOCC_4          MO4_CNT');

    x := least(+c(40), c(41));
    z(least(+x, c(39)));
    z(c(39), 0);
    z(x, 30, 1);

    p(s);
  end;
  procedure showLeapEasterDay is
  begin
    p('ABSENT_START ABSENT_END');
    for i in 22 - 31 .. 25 loop
      x := to_char(v + i, 'mm-dd   ');
      if c(i) = 0 then
        s := nvl(s, x);
      end if;
      if s = s and (i = 25 or c(i + 1) < 0) then
        p(s || x);
      end if;
    end loop;
  end;
  procedure showFoolEasterDay is
  begin
    p('YEAR TOTAL');
    for y in 2011 .. 2099 loop
      if c(y) like '%01' then
        p(y || ' ' || -c(40));
      end if;
    end loop;
  end;
end;
/

使用道具 举报

回复
论坛徽章:
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
32#
 楼主| 发表于 2011-4-28 21:24 | 只看该作者
晕,substr(c(y),-2) = 1 直接改为判断  c(y) = '04-01' 还比 c(y) like '%01' 少一个字节。

使用道具 举报

回复
论坛徽章:
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
33#
发表于 2011-4-28 22:01 | 只看该作者
nyfor太强大了,幸亏你没去当黑客!

使用道具 举报

回复
论坛徽章:
46
凯迪拉克
日期:2013-08-22 10:00:10Jeep
日期:2013-08-10 07:21:13ITPUB社区12周年站庆徽章
日期:2013-10-08 14:57:28ITPUB十周年纪念徽章
日期:2011-11-01 16:20:282012新春纪念徽章
日期:2012-01-04 11:49:54ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:体操
日期:2008-10-24 13:08:31会员2007贡献徽章
日期:2007-09-26 18:42:10马上加薪
日期:2014-04-11 09:34:11秀才
日期:2015-09-06 10:19:32
34#
发表于 2011-4-28 22:58 | 只看该作者
v date := date '1-3-31';
      x := 25 - s - (y - 2344 + trunc(y / 4) - s) mod 7;
      c(y) := to_char(v + x, ' mm-dd');

改为
v date := date '1-4-25';
      x :=  s + (y - 2344 + trunc(y / 4) - s) mod 7;
      c(y) := to_char(v - x, ' mm-dd');

少3Byte.

使用道具 举报

回复
论坛徽章:
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
35#
发表于 2011-4-29 05:45 | 只看该作者
看了看自己的代码,substr(-2)无法改为=,因为我的q是合并后的

for x in 2011..2099 loop
        q:=q||'
'||x||b||o(x);
        if @q,-2)='01' then
                w:=w||'
'||x||b;
        end if;
        end loop;
end;
]','@','substr('),'#',

使用道具 举报

回复
论坛徽章:
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
36#
 楼主| 发表于 2011-4-29 08:11 | 只看该作者
原帖由 cow977 于 2011-4-28 22:58 发表
v date := date '1-3-31';
      x := 25 - s - (y - 2344 + trunc(y / 4) - s) mod 7;
      c(y) := to_char(v + x, ' mm-dd');

改为
v date := date '1-4-25';
      x :=  s + (y - 2344 + trunc(y / 4) - s) mod 7;
      c(y) := to_char(v - x, ' mm-dd');

少3Byte.

最后一步的计算结果改变了,涉及到数组的下标,那么其它地方也要做相应处理,比如:
s := sign(x - 1) + 40; 中的 x - 1 也要修改为 26 - x  这里又会多一个字节。
还有其他的地方需要调整,暂时不去想了。

使用道具 举报

回复
论坛徽章:
46
凯迪拉克
日期:2013-08-22 10:00:10Jeep
日期:2013-08-10 07:21:13ITPUB社区12周年站庆徽章
日期:2013-10-08 14:57:28ITPUB十周年纪念徽章
日期:2011-11-01 16:20:282012新春纪念徽章
日期:2012-01-04 11:49:54ITPUB 11周年纪念徽章
日期:2012-10-09 18:05:07奥运会纪念徽章:体操
日期:2008-10-24 13:08:31会员2007贡献徽章
日期:2007-09-26 18:42:10马上加薪
日期:2014-04-11 09:34:11秀才
日期:2015-09-06 10:19:32
37#
发表于 2011-4-29 20:27 | 只看该作者
关联太多了,牵一发而动全身。

使用道具 举报

回复
论坛徽章:
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
38#
 楼主| 发表于 2011-4-29 22:10 | 只看该作者
s := (11 * s + 4 - trunc((7 * s + 1) / 19)) mod 29;
x := 25 - s - (y - 2344 + trunc(y / 4) - s) mod 7;
s 值最大的可能取值为28,而我们已知 y>=1900
故而 (y - 2344 + trunc(y / 4) -s ) 这部分可以推知,必定 〉0,因此 mod 7 的结果也必定 >=0
故而,我们可以将 (y -2344 + trunc(c / y) -s )加上7的正整数倍后 mod 7 结果将不变。
由此我们加上 7*334 = 2338 继而变成 (y - 6 + trunc(c / y) - s). 最终就是:
s := (11 * s + 4 - trunc((7 * s + 1) / 19)) mod 29;
x := 25 - s - (y - 6 + trunc(y / 4) - s) mod 7;

这样又可以节省 3 个字节,减少为 1192 字节

再次重申,这种推理变换应该不属于出题者禁止的中间结果吧 ?

使用道具 举报

回复
论坛徽章:
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
39#
 楼主| 发表于 2011-4-29 22:16 | 只看该作者
文件上传最终结果,过五一去了。祝大家节日快乐。
easter.sql (1.93 KB, 下载次数: 25)

使用道具 举报

回复
论坛徽章:
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
40#
发表于 2011-4-29 22:20 | 只看该作者
原帖由 nyfor 于 2011-4-29 22:10 发表
s := (11 * s + 4 - trunc((7 * s + 1) / 19)) mod 29;
x := 25 - s - (y - 2344 + trunc(y / 4) - s) mod 7;
s 值最大的可能取值为28,而我们已知 y>=1900
故而 (y - 2344 + trunc(y / 4) -s ) 这部分可以推知,必定 〉0,因此 mod 7 的结果也必定 >=0
故而,我们可以将 (y -2344 + trunc(c / y) -s )加上7的正整数倍后 mod 7 结果将不变。
由此我们加上 7*334 = 2338 继而变成 (y - 6 + trunc(c / y) - s). 最终就是:
s := (11 * s + 4 - trunc((7 * s + 1) / 19)) mod 29;
x := 25 - s - (y - 6 + trunc(y / 4) - s) mod 7;

这样又可以节省 3 个字节,减少为 1192 字节

再次重申,这种推理变换应该不属于出题者禁止的中间结果吧 ?


这才是妙处所在!快变成机器码了。

使用道具 举报

回复

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

本版积分规则 发表回复

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