模拟多重循环解决逻辑问题
请编写程序解答下面 10 个问题:
1、第一个答案是 b 的问题是哪一个?
(a)2;(b) 3;(c)4;(d)5;(e)6
2、唯一的连续两个具有相同答案的问题是:
(a)2,3;(b)3,4;(c)4,5;(d)5,6;(e)6,7;
3、本问题答案和哪一个问题的答案相同?
(a)1;(b)2;(c)4;(d)7;(e)6
4、答案是 a 的问题的个数是:
(a)0;(b)1;(c)2;(d)3;(e)4
5、本问题答案和哪一个问题的答案相同?
(a)10;(b)9;(c)8;(d)7;(e)6
6、答案是 a 的问题的个数和答案是什么的问题的个数相同?
(a)b;(b)c;(c)d;(d)e;(e)以上都不是
7、按照字母顺序,本问题的答案和下一个问题的答案相差几个字母?
(a)4;(b)3;(c)2;(d)1;(e)0。(注:a 和 b 相差一个字母)
8、答案是元音字母的问题的个数是:
(a)2;(b)3;(c)4;(d)5;(e)6。(注:a 和 e 是元音字母)
9、答案是辅音字母的问题的个数是:
(a)一个质数;(b)一个阶乘数;(c)一个平方数;(d)一个立方数;(e)5 的倍数
10、本问题的答案是:
(a)a;(b)b;(c)c;(d)d;(e)e
题目中,每个问题的答案可能会互相影响,需要综合判断。将问题中的 a,b,c,d,e 选项分别记录为 1,2,3,4,5,这样便于循环中将答案递增。首先把所有问题答案置0,然后按顺序依次给每一个问题答案加1,再通过题目中要求对各个答案进行判断,如果答案不符合某个题目的要求,则答案再加1,直到符合为止。如果 5 个选项全部设置了一遍,仍然没有合适的答案,则返回去重新设置上一题的答案。遇到答案为 0 的题目直接跳过不做判断。
A | B | C | D | |
1 | =[0]*10 | >i=1 | ||
2 | for i>0 | >A1(i)=A1(i)+1 | ||
3 | if A1(i)==6 | >A1(i)=0,i=i-1 | next | |
4 | if !func(A8) | next | ||
5 | >i=i+1 | |||
6 | if i==11 | =C6|A1.(char(asc("a")+~-1)).concat() | >i=i-1 | |
7 | =C6 | |||
8 | func | =A1(A1(1)+1) | if B8!=0 && B8!=2 || A1(to(A1(1))).pos(2)>0 | return false |
9 | if A1(2)!=0 | =A1(2)+1 | ||
10 | if A1(C9)*A1(C9+1)>0 && A1(C9)!=A1(C9+1) | return false | ||
11 | if A1.pselect(~>0 && ~==~[1] && #!=C9)>0 | return false | ||
12 | if A1(3)!=0 | =A1([1,2,4,7,6](A1(3))) | ||
13 | if C12!=0 && C12!=A1(3) | return false | ||
14 | =A1.count(~==0) | =A1.count(~==1) | ||
15 | if A1(4)!=0 | =C14-A1(4)+1 | ||
16 | if C15>0 || C15<0 && B14==0 | return false | ||
17 | if A1(5)!=0 | =A1([10,9,8,7,6](A1(5))) | ||
18 | if C17!=0 && C17!=A1(5) | return false | ||
19 | if B14==0 | =A1.align@a([2,3,4,5]).(~.len()) | ||
20 | if !((A1(6)!=5 && C19(A1(6))==C14)|| (A1(6)==5 && C19.pos(C14)== null)) | return false | ||
21 | if A1(7)!=0 | if A1(8)!=0 && abs(A1(8)-A1(7))!=5-A1(7) | return false | |
22 | if A1(8)!=0 | =C14+A1.count(~==5)-A1(8)-1 | ||
23 | if C22>0 || C22<0 && B14==0 | return false | ||
24 | if B14==0 | [[2,3,5,7],[1,2,6],[0,1,4,9],[0,8],[0,5,10]] | ||
25 | if C24(A1(9)).pos(A1.count(~>=2 && ~<=4))== null | return false | ||
26 | return true |
https://try.esproc.com/splx?38E
A1将各个问题答案置0,B1设置当前的题号i,从第1题开始循环设置答案。
A2用for循环遍历当前题目的每个答案。在循环代码块中,B2将本题答案递增,B3判断答案为5说明本题答案循环完成,此时将本题答案置零,返回上一道题继续循环。在每次循环中,B4用A8子程序判断当前的选择是否与题目要求有冲突,如果产生了问题则继续循环本题的下一个答案。如果目前的选项没有发现问题,则可以开始选择下一题。在A6中判断是否此时全部题目都已经选择了答案且满足题目要求,如果成立说明A1中选择的答案为1组可行解答,将其记录在C6中。这里用char和asc函数将答案的整数转换为字母,并用concat函数将序列拼为直观的字符串。
再来看A8为首格的子程序,这个子程序并没有用到参数,而是直接用A1中的答案执行判断,也没有给子程序命名,此时调用子程序时,只需如同B4中用func()指明子程序的首格。
在子程序中,第8行根据第1题答案中对应的题号,判断是否有错误。先选出对应题目的答案,再判断它是否为第一个b,如果不成立说明第1题目前的答案是错的,子程序返回false。如果对应题目答案为0,说明尚未选择,此时并不认为第1题答案有错误。在SPL中,to(n)可以取得1~n构成的序列,用其可以取得答案选择的题目及之前的所有答案,用A.pos(x)来判断其中是否存在其它选2(对应b)的;而使用与(||)或(&&)非(!)等逻辑操作符可以执行复杂的判断。
9~11行,判断第2题答案。第2题如果未选择,并不认为有错误。C10判断对应的两题答案是否相同,同样只有它们全都确认了答案才判断,如果不相同则返回false。C11则判断是否还有其它相邻答案有相同的情况,其中~[1]表示下一题的答案,SPL的这种语法可以很方便地执行跨行计算。
12~13行,继续判断第3题答案。为此,先取出对应题号的答案,再判断是否与第3题答案相同。
B14统计A1中未确认答案的题目总数,C14则计算共有多少道题选择了a。SPL用count()函数计算符合条件的成员总数。
15~16行判断第4题答案,这需要A1中所有答案都已确定时才能完成判断,看选择a的题目总数是否与答案符合。
17~18行判断第5题答案,判断其对应的题目答案是否与当前答案相同。
19~20行判断第6题答案,与第4题类似同样需要所有答案都已选定。C19计算b,c,d,e在答案中各出现几次,其中align@a(A)将序列按照A的顺序对应分组,再计算出每个分组中的成员总数。C20判断第6题答案是否有错,对于前4个选项,判断对应的答案是否与a出现的次数相同;如果选择e则需要判断是否a出现的次数与其它选项都不相同。
第21行判断第7题答案,看第7题和第8题的答案是否相差1,这个判断需要第8题选定了答案时才执行。在SPL中可以使用各种数学函数,如abs()用来求绝对值,这和Excel等工具中的情况是相同的。
22~23行判断第8题答案,这需要A1中所有答案都已确定时才能完成判断,看选择a和e的题目总数是否符合答案。
第9题的答案比较复杂,在判断时,在可能出现的题目总数0~10中,分别选出质数、阶乘数、平方数、立方数和5的倍数,再在C25中根据第9题的答案判断选择bcd这3个选项的总题数是否符合答案。
第10题实际上每个选项都可以,它只会影响前面题目的判断。如果前9题均正确,即可确定当前解答符合要求。
本题每道题都有5个答案,实际上相当于10重嵌套循环,通过设置A1中的答案数组,用单层循环模拟了多重循环等效的操作,由于在每道题选择答案后及时判断是否错误,也避免了多余的循环操作。如果要执行多重循环,则需要计算5^10次判断,这是相当繁重的工作,性能会比这种方法差得多。代码执行后,只有一组解答满足要求:
英文版