声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 5171|回复: 26

[C/C++] 放松一下,来个编程挑战(不限于C/C++,而且答对有奖励)

[复制链接]
发表于 2010-10-16 10:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
咱们论坛的帖子多以问/答为主,今儿来点脑筋急转弯吧。

这个问题很早在CSDN/C版上看到过:

要求实现这样的函数:
int p(int i, int N);
功能:调用该函数,打印如下格式的输出,例p(1, 7);
1
2
3
4
5
6
7
6
5
4
3
2
1
即每行一个数字。(注意:N只打印一次)
要求:
1. 函数中唯一能够调用的函数就是printf。(是不是意味着不能递归?)
2. 不准使用如下的关键字:typedef, enum, do, while, for, switch, case, break, continue, goto, if。 (通常的循环也别想了?)
3. 不能使用逗号表达式和?:表达式。
4. 函数中只能有一条语句(就是只能出现一个;)。


PS:如果你使用其他语言,也请尽量满足对应语言中与上述4条相对应的规则,并作出相应的说明!


怎么样,各位,贴出你的解决方案吧,我私自做主了,一个转贴的答案+5点体能一个原创的答案+1点威望


=================================解答分割线===========================
第一个满足全部约束条件的代码如下,由wqsong 提供,使用C语言巧妙地实现,详细分析见10L、15L、17L等:

  1. int p(int i, int N)
  2. {
  3.         return (*((short *)&i+1) || (*((short *)&i+1) = *(short *)&i)) && *(short *)&i <= (2*N - (*((short *)&i+1))) &&  printf("%d\n", N - (N - *(short *)&i) * (2*(*(short *)&i < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*(short *)&i;
  4. }
复制代码

第二个?It's up to you!
回复
分享到:

使用道具 举报

发表于 2010-10-18 00:40 | 显示全部楼层
。。。神马奖励???
发表于 2010-10-18 00:42 | 显示全部楼层
应该只能用递归函数的,不用递归函数只能内嵌汇编了。。。;@P
发表于 2010-10-18 00:50 | 显示全部楼层
本帖最后由 wqsong 于 2010-10-18 10:09 编辑
  1. int p(int i, int N)
  2. {
  3.         return i<N && printf("%d\n", i) && !p(i+1, N) || printf("%d\n", i);
  4. }
复制代码
直接看有点绕,分解一下,有点类似与二叉树的后序遍历:

  1. int p(int i, int N)
  2. {
  3.         if(i<N)
  4.         {
  5.                 printf("%d\n", i);
  6.                 p(i+1, N);
  7.         }
  8.         printf("%d\n", i);
  9. }
复制代码
以上这段不难懂,从上往下分别用到i<N,printf("%d\n", i),p(i+1, N),printf("%d\n", i)。。。
返回一个bool值。。。再用&&和||的短路特性连接一下就可以了。。。

评分

1

查看全部评分

发表于 2010-10-18 01:36 | 显示全部楼层
python的一个,python 2.5.4的print不带返回值,3.0以后好像带返回值,改写一下,有点多。。。
  1. def printf(i):
  2.         print i
  3.         return i
复制代码
  1. def p(i, N):
  2.         return i<N and printf(i) and not p(i+1, N) or printf(i)
复制代码

评分

1

查看全部评分

发表于 2010-10-18 10:05 | 显示全部楼层
本帖最后由 wqsong 于 2010-10-18 10:07 编辑
  1. int p(int i, int N)
  2. {
  3.         return (i<N) * printf("%d\n", i) && p(i+1, N) && 0 || printf("%d\n", i);
  4. }
复制代码
这样也可以。。。有点fuck brain。。。
发表于 2010-10-18 10:24 | 显示全部楼层
本帖最后由 wqsong 于 2010-10-18 10:33 编辑
  1. int p(int i, int N)
  2. {
  3.         printf("%d\n", i) && i<N && p(i+1, N) && printf("%d\n", i);
  4. }
复制代码
再发一个,return语句都省了。。。没返回值和函数原型有点不一样,但是符合C89标准。
 楼主| 发表于 2010-10-18 10:29 | 显示全部楼层
回复 wqsong 的帖子

不错不错,不过原问题中有一个限制没有满足:
1. 函数中唯一能够调用的函数就是printf。

是不是意味着甚至不能调用P()本身?

不过谢谢你积极的参与和非常有创意的工作,分加上了,有空常来逛逛。
发表于 2010-10-18 10:38 | 显示全部楼层
回复 Rainyboy 的帖子

。。。应该不限制递归吧
再想想看有么有不用递归的办法。。。
发表于 2010-10-18 13:49 | 显示全部楼层
本帖最后由 wqsong 于 2010-10-18 14:50 编辑

想了一会,估计不用递归的话,修改IP寄存器也能做到。。。有点繁琐,而且调用也有限制。。。
假设有这样的调用:
p(int i, int N);

对应的汇编应该是:
……
push N
push i
call p
……

因为call指令要执行的是push eip(这里不考虑段间调用),所以实际上在栈中存储是这样的
+--------+
|     …    |         <-这里是低地址
+--------+
|    eip    |
+--------+
|      i      |
+--------+
|     N     |
+--------+
|     …    |         <-这里是高地址
+--------+
所以IP实际的压栈位置应该是((unsigned *)&i - 1)(按32位机器算,一个指针占4字节),每次把这位置的值修改到call foo处,就能达到目的。
原理是这样的,估计实现的时候还有其他问题,当然和编译器也有关。。。

当然,同理,如果知道printf()函数具体怎么实现的话,直接修改进入printf函数时候的IP指向也可以。。。
就不写了,娱乐一下拉到。。。:lol

评分

1

查看全部评分

 楼主| 发表于 2010-10-18 13:53 | 显示全部楼层
回复 wqsong 的帖子

好吧……确实很程序员方式的娱乐,有空我还真想试试你所说的方法,估计等两天吧
发表于 2010-10-18 14:01 | 显示全部楼层
回复 Rainyboy 的帖子

嗯嗯,有空我也试一试。。。
快毕业了,忙的找工作,什么心情也没有。。。嘿嘿
发表于 2010-10-18 23:19 | 显示全部楼层
本帖最后由 wqsong 于 2010-10-19 01:22 编辑
  1. int p(int i, int N)
  2. {
  3.         return (*((short *)&i+1) || (*((short *)&i+1) = *(short *)&i)) && *(short *)&i < 2*N && *(short *)&i <= (2*N - (*((short *)&i+1))) &&  printf("%d\n", N - (N - *(short *)&i) * (2*(*(short *)&i < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*(short *)&i;
  4. }
复制代码
再写一个,当作我的最终版吧。。。
只用到了printf函数,没有显式的递归。隐式修改eip实现递归。同时把i变量分为两半用,是一个16位过程。当然和编译器实现有关,在VC9,GCC3.4.5均能实现。

评分

1

查看全部评分

 楼主| 发表于 2010-10-19 22:16 | 显示全部楼层
回复 wqsong 的帖子

真是有朋自远方来不亦说乎啊!欢迎你有空常来这边逛逛
 楼主| 发表于 2010-10-20 10:34 | 显示全部楼层
本帖最后由 Rainyboy 于 2010-10-20 10:59 编辑

我来慢慢重构,理解你的代码:

源代码:

  1. int p(int i, int N)
  2. {
  3.         return (*((short *)&i+1) || (*((short *)&i+1) = *(short *)&i)) && *(short *)&i < 2*N && *(short *)&i <= (2*N - (*((short *)&i+1))) &&  printf("%d\n", N - (N - *(short *)&i) * (2*(*(short *)&i < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*(short *)&i;
  4. }
复制代码
第一步:

  1. int p(int i, int N)
  2. {
  3.        short *funcp = (short *)&i;
  4.        return (*(funcp+1) || (*(funcp+1) = *funcp)) && *funcp < 2*N && *funcp <= (2*N - (*(funcp+1))) &&  printf("%d\n", N - (N - *funcp) * (2*(*funcp < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*funcp;
  5. }
复制代码
第二步:


  1. int p(int i, int N)
  2. {
  3.       short *funcp = (short *)&i;
  4.       if((*(funcp+1) || (*(funcp+1) = *funcp)))
  5.       {
  6.            return *funcp < 2*N && *funcp <= (2*N - (*(funcp+1))) &&  printf("%d\n", N - (N - *funcp) * (2*(*funcp < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*funcp;
  7.       }
  8.      else
  9.      {
  10.           return 1;
  11.       }
  12. }
复制代码
第三步:


  1. int p(int i, int N)
  2. {
  3.       short *funcp = (short *)&i;
  4.       if((*(funcp+1) > 0))
  5.       {
  6.            return *funcp < 2*N && *funcp <= (2*N - (*(funcp+1))) &&  printf("%d\n", N - (N - *funcp) * (2*(*funcp < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*funcp;
  7.       }
  8.       else
  9.       {
  10.           *(funcp+1) = *funcp;
  11.           if(*(funcp+1) > 0)
  12.           {
  13.                return *funcp < 2*N && *funcp <= (2*N - (*(funcp+1))) &&  printf("%d\n", N - (N - *funcp) * (2*(*funcp < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*funcp;
  14.           }
  15.           else
  16.          {
  17.               return 1;
  18.          }
  19.      }     
  20. }
复制代码

第四步:

  1. int p(int i, int N)
  2. {
  3.       short *funcp = (short *)&i;
  4.       //i的低位存于funcp中,用于计数
  5.       //i的高位存于funcp+1中,用于储存i的实际值
  6.       if((*(funcp+1) > 0))//该分支用于判断是否初始化
  7.       {
  8.             //if(*funcp < 2*N)//该分支用于判断是否到达打印次数:多余的判断!
  9.             //{
  10.                   if(*funcp <= (2*N - (*(funcp+1))))//该分支用于判断是否到达打印次数
  11.                   {
  12.                         printf("%d\n", N - (N - *funcp) * (2*(*funcp < N) - 1));//执行打印
  13.                         *((unsigned *)&i - 1) -= 5;//调整堆栈中eip的值
  14.                         ++*funcp;//计数器自增
  15.                   }
  16.                   return 1;
  17.             //}
  18.             //return 1;
  19.       }
  20.       else
  21.       {
  22.             *(funcp+1) = *funcp;
  23.             if(*(funcp+1) > 0)
  24.             {
  25.                   //if(*funcp < 2*N)//该分支用于判断是否到达打印次数:多余的判断!
  26.                   //{
  27.                         if(*funcp <= (2*N - (*(funcp+1))))//该分支用于判断是否到达打印次数
  28.                         {
  29.                               printf("%d\n", N - (N - *funcp) * (2*(*funcp < N) - 1));//执行打印
  30.                               *((unsigned *)&i - 1) -= 5;//调整堆栈中eip的值
  31.                               ++*funcp;//计数器自增
  32.                         }
  33.                         return 1;
  34.                   //}
  35.                   //return 1;
  36.             }
  37.             return 1;
  38.       }
  39. }
复制代码
第五步:
通过上述重构发现你的代码中似乎存在一条多余的判断,见上述注释。
因此,将这条判断减去,并且重新合并后,修正一个版本:

  1. int p(int i, int N)
  2. {
  3.         return (*((short *)&i+1) || (*((short *)&i+1) = *(short *)&i)) && *(short *)&i <= (2*N - (*((short *)&i+1))) &&  printf("%d\n", N - (N - *(short *)&i) * (2*(*(short *)&i < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*(short *)&i;
  4. }
复制代码
即:

  1. int p(int i, int N)
  2. {
  3.         return (*((short *)&i+1) || (*((short *)&i+1) = *(short *)&i)) /*&& *(short *)&i < 2*N*/ && *(short *)&i <= (2*N - (*((short *)&i+1))) &&  printf("%d\n", N - (N - *(short *)&i) * (2*(*(short *)&i < N) - 1)) && (*((unsigned *)&i - 1) -= 5) && ++*(short *)&i;
  4. }
复制代码

您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-5-10 06:38 , Processed in 0.266679 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表