文/王德贵
中国古代数学巨著《九章算数》是张苍、耿寿昌所撰写的一部数学专著。其内容十分丰富,总结了战国、秦、汉时期的数学成就。是当时世界上最简练有效的应用数学,它的出现标志中国古代数学形成了完整的体系。其中有一道题是“五家共井”问题,原文如下:
五家共井,甲二绠不足,如乙一绠;乙三绠不足,如丙一绠;丙四绠不足,如丁一绠;丁五绠不足,如戊一绠;戊六绠不足,如甲一绠,皆及。
这道题的白话解释是:五家合用一口井,甲家的2根井绳和乙家1根井绳总长为井深;乙家的3根井绳和丙家的1根井绳总长为井深;丙家的4根井绳和丁家1根井绳总长为井深;丁家的5根井绳和戊家1根井绳总长为井深;戊家的6根井绳和甲家1根井绳总长为井深。问:井深、各家井绳各多少?(每家的井绳均等长)
下面我们也来分析一下五家共井问题,并用Python、图形化和APPInventor分别求解。
一、创意来源
在教授学生学习Python四级课程时,合用的练习和案例并不多,于是在搜索案例过程中,看到了这个“五家共井”问题,经过研究发现比较适合用Python四级的知识点来解决,现分享出来。
二、设计思路
这是一个不定方程问题。遇到方程最初的想法还是用枚举法,在100范围内运行后,无果。说明最小正整数解,一定比100大,于是扩大范围到300,结果运行很久也没有输出结果,看来运算时间过长了,没有能等到程序运行出结果。
于是想到库函数sympy,它是一个符号计算的Python库。我在文章《阿基米德群牛问题的分析及Python验证》里讲过,这里不再赘述。
通过解方程,得到关系式,从而求出最小正整数解。
在使用Python求解过程中,想试着再用Scratch和APPInventor求解,通过编程,运行,在对比三种代码之后很有启发,下面把求解过程分享给大家。
三、程序设计
(一)Python程序设计
1.枚举法
这是一种最直接是思路,不知道具体结果,那就用枚举法测试。
由于运行时间较长,运行时将消耗时间打印出来了,此时显示的是运行了a取值1到10的运行时间222秒。
2.时间复杂度
如果取值范围在100以内,则时间复杂度是10的10次方,按运行时间算,运行了10个a将近4分钟,那运行100个a,需要的时间就大约是40分钟。
当a的取值在1~300时,运行1个a需要的时间将近30分钟,那300个a就是近150个小时,需要6天多的时间。
这样长的运行时间完全无法实用,必须通过缩减无效运算来优化程序。改为根据最短的绳子e作为枚举的主要参数,根据网络搜索答案,我已经知道e的解小于100,等待一段时间能够获得答案。
运行10个e的时间将近是6分钟,随e值增大,单次运算时间还会缩短。优化后,运行时间大大缩短了,只需25分钟左右,已经获得了一组结果。
我们根据已有答案回推优化程序,最终获得了结果。但是如果我们不知道答案的范围,即使只在300范围内试算,运行也要6个小时左右。枚举法在面对这样一个不定方程的情况,如果不知道结果的范围,那么运行时间就会非常长!必须去寻找更简捷的算法。
3.方程解法的程序设计
(1)利用Sympy库函数先求出不定方程的关系式
运行结果:
因为绳长是整数,所以e一定是76的倍数,因此可以求出最小正整数解:甲:265,乙:191,丙:148,丁:129,戊:76;井深:721。
即甲家井绳长265,乙家井绳长191,丙家井绳长148,丁家井绳长129,戊家井绳长76,井深721。
(二)Scratch程序设计
1.基本思想还是枚举,利用附加条件循环。
2.程序说明
注意的是,几个条件都应该是“与”的关系,4个条件截图不全。如果满足条件,则说5秒。
程序是5重循环,每个都是300次,a在最外层,运行了1次,就相当于运行了4重300次,就是300×300×300×300次,用了将近24小时,a要是运行300次,总时长则大约需要300天!
3.优化
必须要优化程序,缩小取值范围。
运行时间6个e,大约3.5小时,但e越大,相对运行时间会越短,所以总运行时间大大缩短了。
但是毕竟时间复杂度太大,Scratch运行效率又太低,总时长还是太大,即使用优化程序测试结果,也需要两天左右的时间。
(三)APPInventor程序设计
1.设计思路
在Python测试时,在电脑上运行速度还是很快的了,但在手机上运行,则更依赖于手机的配置,明显感觉运行的很慢很慢。所以加上了直接验证的程序代码。
2.程序设计及说明
(1)变量和初始化
变量“枚举验证”是使用枚举法还是验证数据的转换开关。
变量“分解列表”是在验证的时候,分解输入的数据,并放在列表中,以备程序调用。
初始化程序,一是初始化程序为枚举状态,二是提示先选择使用“枚举”还是“验证”。
(2)枚举
点击“枚举”按钮,输入相关数据。因为验证时不需要水平布局4,被程序隐藏,所以使用“枚举”时,必须让其显示出来。
(3)验证
点击“验证”即可验证数据是否正确。验证数据只需要连续输入数据,所以将水平布局4隐藏。并将标签1的文本做输入提示。
(4)提交
提交时先读取是验证状态,还是枚举状态。
然后判断输入框是否为空,当不为空时,则执行程序。
验证状态:
先将输入框的数据分解成列表,再判断5组数据是否满足条件。
如果满足,则显示五个对应的数据,并提示:验证正确,否则提示:验证错误。
这个运行速度很快。
枚举状态:
按照提示,先输入取值范围和初始值和结束值,然后点击提交即可。 枚举APP界面如下。
在75-80范围内,速度很快,但在75-300范围内,手机一直在运行过程中没有反馈,就像死机了一样,虽然我知道程序还在后台运行。但这个运行时间肯定会很久,所以就没有坚持下去的必要了。判断满足条件的5个值,代码如下。
程序进行了优化,a的取值由b开始到结束值,而b值由c到结束值,以此类推,d是取e到结束值,而e是从开始值到结束值。这样运行时间会减少很多,但由于运行速度和时间与手机配置直接相关,所以虽然运算量已经大大减少,还是很难去等一个结果。
如果满足条件,则显示五家的绳长和井深,否则提示在开始值 到结束值范围内无解。
四、测试与改进
三种方法,经过测试,用Python运行最快,APPInventor最慢(使用优化程序仍然无结果输出),只是APPInventor更直观些。大家有兴趣,可以自行验证,本文不做赘述,这也是自己的学习心得,有不妥之处,请不吝赐教!
★《布宫号》提醒您:民俗信仰仅供参考,请勿过度迷信!