超级短的C语言程序,一个简单的 短码 实例 ( C语言 )

最近突发奇想,不知为何对短码上瘾了,虽说短码不利于工程,因为很难看懂,但是能写出牛逼短码的程序员都是高手这一事实是不会改变的,那我今天刚好无聊缩了个小程序,发出来交流交流。

题目很简单:

对任何一个自然数n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把(3n+1)砍掉一半。这样一直反复砍下去,最后一定在某一步得到n=1。求给一个数字,要多步不才能使得n=1

首先是没缩短之前的源代码: 一共是15行

#include

int main(){

int n,sum = 0;

scanf("%d",&n);

while( n!=1 ){

if( n % 2 ){

n = (3*n+1)/2;

}else{

n /= 2;

}

++sum;

}

printf("%d\n",sum);

return 0;

}

代码很清晰,乍一看没什么可以缩减的,我们来一步一步缩。

首先改造while循环里面的if语句,用三目运算替换,得到:

n%2 ? n = (3*n+1)/2: n /= 2;

这样一下子就缩短了4行,从5行变为了1行,其实这种if语句的缩短是很基础的,而且三目运算在短码里面有着举足轻重的地位,非常普遍,掌握三目运算是很重要的。

然后我们发现sum这个变量除了累加没有别的操作,我们可以继续并入刚才的那一行。

n%2 ? n = (3*n+1)/2: n /= 2,++sum;

于是我们就又缩短了一行,由于while循环里面只一条语句,于是将大括号去掉,然后我们来看看整个代码:共9行

#include

int main(){

int n,sum = 0;

scanf("%d",&n);

while( n!=1 )

n%2 ? n = (3*n+1)/2: n /= 2,++sum;

printf("%d\n",sum);

return 0;

}

这么一看好像差不多了,但是这还远远不够,刚才提到了if语句的一个缩短方法,其实一般的短码中不会出现while循环,因为while循环功能太少,而for循环的两个分号隔开的三段既可以有初始,又有判断语句,然后又有一般作为累加段的常用语句段,于是我们接下来做第二次的大缩减。

于是while循环就变成了这个样子

for( ; n != 1 ; n%2 ? n = (3*n+1)/2: n /= 2,++sum);

这样一来又缩减了一行,然后我们继续研究一下整个代码:

#include

int main(){

int n,sum = 0;

scanf("%d",&n);

for( ; n != 1 ; n%2 ? n = (3*n+1)/2: n /= 2,++sum);

printf("%d\n",sum);

return 0;

}

首先很快的我们可以把scanf放入for循环中这个很容易想到,但是printf呢?

这时候我们应该可以想到printf会输出的条件是循环的跳出,于是可以将printf放入for的第二个语段里面,于是稍加改造成了这个样子

for( scanf("%d",&n); n != 1 ? 1:(printf("%d\n",sum),0) ; n%2 ? n = (3*n+1)/2: n /= 2,++sum);

这里面有几个注意点,也主要是如何把printf加入到for循环中的注意点:

1. 第二条语句肯定要有返回值,不是0就是非0来给出for循环是否结束

2. (x,y)这个表达式的返回值是y

这两个注意点注意了之后就很好办了,代码就可以很简单的缩减成这个样子了。

我们继续看看现在整个代码是什么样子:一共是6行

#include

int main(){

int n,sum = 0;

for( scanf("%d",&n); n != 1 ? 1:(printf("%d\n",sum),0) ; n%2 ? n = (3*n+1)/2: n /= 2,++sum);

return 0;

}

纵观整个代码前两行和后两行应该是没什么好缩短的了,况且也没啥意思,for循环一行搞定,不可能再从1行缩减到0行,因此只有变量的定义这部分了,那么这个能不能归并到别的行呢,答案是肯定的,我们要注意到一点,main是一个函数,因此可以有参数,最终的代码为:

#include

int main(int n,int sum){

for(sum = 0,scanf("%d",&n) ; n!=1?1:(printf("%d\n",sum),0); n%2?n = (3*n+1)/2:n /= 2,++sum);

return 0;

}

一共只有5行,作为这个程序的主体部分也就是for循环,只一行,本次短码实例到此结束。

PS: 貌似VS编译不通过的样子,我同学说的,我不清楚,因为我一直都是用的Code::Blocks是GNU的标准,我自己编译没啥问题。

------------------------------分割线------------------------------

有同学继续对我的进行了修改,减少了几个字节,我觉得有必要贴出来,能少多少就少多少,追求最好嘛。

#include

int main(int n,int sum){

for( sum = 0,scanf("%d",&n) ;  n!=1?1:!printf("%d\n",sum) ; n =( n%2?(3*n+1):n) >> 1,++sum);

return 0;

}

最后再次声明,短码不利于工程,Just for fun,大家玩玩就行,在实际的工作学习中不要养成这个习惯,我也只是最近突然对这个来了兴趣,觉得有更好的方法,或者可以再缩短的欢迎交流。谢谢! 最后附上壁纸一张,前两篇都是风景,这次来个动漫的,我的第三篇博客到此结束。

0818b9ca8b590ca3270a3433284dd417.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值