撒旦变脸并不可怕,本质亦须真知来抓
编程爱好者
上一回见识了阿基米德公式的威力,现在,再回到远古的希腊,来看看西方一位以作恶而昭著的人物——他就是撒旦。
撒旦(Satan),西方神话中的人物,上帝和人类的邪恶敌人,通常被认为是堕落天使的领袖,不折不扣的恶魔,他有一个最好的把戏,就是在不同人的面前可以显现不同的面目——变脸,但不论怎么变,却一个信徒也没有。令撒旦想不明白的第一个问题是,耶稣怎么会有那么多跟随者呢?
有一天,耶稣带领众信徒上山传教时,撒旦也决定去看个究竟。
第一天,耶稣对徒弟们说,是我的徒弟的,你们一人捡两块石头,跟我一起走。于是,徒弟们一人拿起两块石头,向山上走去。撒旦心想,大的太重,于是捡了两块最小的石头。到了山上,耶稣依次看徒弟们手中的石头,当看到撒旦时,耶稣拿了块小的石头,说:你是撒旦吧。撒旦很纳闷,心想,一定是拿的石头太小了,露馅了,灰溜溜地走了。
第二天,耶稣依然带领他们上山,并且照旧让他们每人捡两块石头。撒旦变了另外一张脸,心想,昨天我捡了两块最小的,今天我要捡两块最大的。到了山上。耶稣还是轮着看,走到撒旦面前时,拿了块大的,又笑着说:你是撒旦。撒旦又灰溜溜地走了。
第三天,上山时,耶稣又让他的徒弟们捡两块石头。撒旦变了脸,心想:第一天我捡了两块最小的,第二天捡了两块最大的,都露了馅。今天我捡一大一小,就万无一失了。于是他捡了一大一小两块石头上了山。到了山上,耶稣还是轮着看,走到撒旦面前时,又挑了块大的,接下来耶稣还是笑着说:你是撒旦!
撒旦弄不明白的第二个问题是,耶稣怎么老将我认出来呢?耶稣又笑着说,你的变脸游戏挺不错的,不过我给提点建议,在做之前,穿上鞋子,你是六指呀!撒旦当时昏倒在地!
我们的问题是:耶稣接过的三块石头,请按从大到小排一下。
撒旦变脸解析:
第一步:树梯子
这是最简陋的一个图形,也是最基本的一步,“目”形图,我们略去,从第二步开始。
第二步:做头尾
上面的三部分,先分析开头和结尾部分,开头是什么呢?题中的已知条件,是三块石头重量,我们用a、b、c来表示。目标是什么呢?是从大到小的三个数。怎样表达呢?第一种方式中,输出还是用a、b、c,但这三个a、b、c和输入的不尽一样,输入的值有六种可能,而输出只有一种(见图1B);第二种方式是直接输出这六种方案中的一种(见图1A)。


第三步:连头尾
如何将开头和结尾连接起来呢?出现上面的两种思路,第一种,除了找到最大的,还要找出中间的,因为是三个数,所以前两个找对了,最小的也就有了。怎样才是真正的最大值,将这个过程分析一下,可以分成两步:第一步,将a和b比较,使a>b;第二步,将a和c比较,使a>c,通过此两步比较完成,a的值一定就最大了,如图2B中间所示。还有是如何确定第二大的,这个问题只要一步就可解决,比较b和c,使b>c。所以该问题经过三步可解决,这三步都是相似的分支结构(如图3B所示),构成了一个摞在一起的分支结构程序。


那每一个小小问题又如何解决呢?
先看第一步,比较a和b,使a>b 。这个题目仔细分析一下,正是两个数大小排序的问题,两种情况将来会出现一种,恰好用一个分支就可以解决掉,该问题可分成三部分,在分支的右边的情况中,又恰好出现我们第一回中遇到的哥伦布水杯问题。第一步和第二、三步是类似的,只要将a、b换成a、c或b、c就有了,正是第二、三步和第一步的这种相似性,程序稍稍一变换就有了。
第二种思路该如何解决呢?
输出“六种方案中的一种”,当然要用分支结构,但一个分支又只能解决二选一的问题,怎么办呢?可以将这六种方案合成两大类,后面可以再将合并的分开,问题就得到了解决(如图2A所示)。每一个分支中又包含了三种情况,所以还要将各自的三种情况再合并成两种,通过分支解决,即分成二选一的情况和一种的情况,在二选一的情况中还要再用一个分支,由此我们可以看出,分支和分支嵌套了三层之多(如图3A所示)!三层中的逻辑关系,请大家看仔细了。


第四步:贴语法
下面我们还用QBASIC语言来解这个题目。第三步图中的各个语句和具体语言的语法还有一定的差距,根据相应语言,主要体现在输入和输出语句中,还要再行将相应语句转化。
第五步:写代码
下面可以写代码了,两个程序中,第一种方法的代码较简单,第二种的代码比较难写,但如果我们遵循下面的原则,也就比较简单了,先整体分块,然后从整体到部分。
第一种方法(如图3B所示),整个图分成了五大部分,复杂一点的是中间的三部分,第一部分和最后一部分最简单,写的过程中要注意代码的开始和结束标志。第一种代码如下:
input a,b,c
if a>b then
else
d=a
a=b
b=d
endif
if a>c then
else
d=a
a=c
c=d
endif
if b>c then
else
d=b
b=c
c=d
endif
print a,b,c
第二种方法(如图3A所示)整个图可分成两大部分,下面的分支作为一部分,这部分比较复杂,上面的一部分原封不动照搬,非常简单。写完这一部分后,要注意先将下面的分支的框架形式写好,然后通过填空的形式向上填,这样就不容易出错了,后面还要注意使用代码里嵌风格,这样更容易分清代码和代码的关系和脉络。代码如下:
input a,b,c
‘第一层分支
if a>b then
if c>a then
print c ,a ,b
else
if c>b then
print a,c,b
else
print a,b,c
end if
end if
else
if c>b then
print c,b,a
else
if c>a then
print b, c, a
else
print b, a,c
end if
end if
endif
(上程序在Qbasic下调试通过)
阿兰开讲
程序演义到现在,由于多种分支结构的出现,解决的问题呈现出多姿多彩的形式,不管怎么变,分支只有两种形式,上下摞在一起形成一种顺序关系,或嵌套而形成连环分支的套加式,但不管怎样,都是为解决更多种情况而存在的。
问题与问题之间的联系也紧密起来,看似很不起眼的小小哥伦布水杯问题,竟然又出现在题目中,还屡试不爽。进一步引伸一下,不难得出下面的结论:大题目其实都是由小题目组成的。
我们还可将本题引伸一下,研究一下两个数排序,会有许多精彩的东西出现。一个最简单,两个稍复杂,三个更复杂,那面对一百个呢?有意思的问题可能正在这里,“3”是个有意思的数字,可能会因之而搔头,也可能会因之而慨叹!
阿兰告诉大家的是:在编程方面,撒旦脸蛋的变化告诉我们的更重要的是,要抓住本质,也要学会找出规律,办法总比困难多。(赵玉勇 徐媛)
22期小测验参考答案:
我们可以给自己提个问题:人民币为什么不是从1元到100元都有相应的纸币呢?没有,可并没有妨碍我们每天花钱,但花的时候往往不是恰好是我拿的那些钱,但这并不妨碍我们,因为可以找零啊。有了人民币的经验,我们就可以分了,两次弄断就应分成三份,可以把金条分成1/7、2/7和4/7三份,应用用找零的原理,题目就不难解决了。这样,第1天我就可以给他1/7;第2天我给他2/7,让他找回我1/7;第3天我就再给他1/7,加上原先的2/7就是3/7;第4天我给他那块4/7,让他找回那两块1/7和2/7的金条;第5天,再给他1/7;第6天和第2天一样;第7天给他找回的那个1/7。