孫學進 王德貴
有人問我,天天研究數(shù)學問題,數(shù)學到底哪里有趣了?數(shù)學之美又在哪里?其實,當你研究深入后,會發(fā)現(xiàn)數(shù)學真的很奇妙!也有很多未解之謎,今天我們來了解一下數(shù)學黑洞“6174”。
數(shù)學黑洞,就是無論怎樣設值,在規(guī)定的處理法則下,最終都將得到固定的一個值,再也跳不出去了,就像宇宙中的黑洞可以將任何物質包括光都牢牢吸住,不使它們逃脫一樣。
數(shù)學黑洞6174,又稱卡普雷卡爾(Kaprekar)常數(shù)。內(nèi)容是:
取一個4位數(shù)(4個數(shù)字全相同的除外),將該數(shù)的4個數(shù)字重新組合,形成可能的最大數(shù)和可能的最小數(shù),再將兩者之間的差求出來;對此差值重復同樣過程,不足4位在末位補0,最后你總是會得到6174陷入卡普雷卡爾黑洞,而且經(jīng)過我的驗算到達這個黑洞最多需要7個步驟(注:百度百科上說,是14個步驟,存疑)。
今天我們用Python、圖形化(SC)和APPInventor來做驗證。
有趣的數(shù)學問題,加上Python編程,真是絕妙的搭配!近期也一直在和大家分享我的學習過程。在Python等級考試4級學習中,遇到了這個問題,經(jīng)過一段時間的研究、探討和分析感到收獲頗多,分享給大家,希望能提高你學習Python的興趣。
這是一個驗證的問題,也要解決以下3個問題。
一是輸入任意一個4位數(shù)(不包含全部相同的數(shù)字),驗證最后經(jīng)過運算是不是都得到“6174”;二是在一定范圍內(nèi),是不是都能得到“6174”;三是得到“6174”最多需要多少個步驟。
首先要將4位數(shù)分解開單個數(shù)字,存儲在新列表中,然后排序列表,輸出最大和最小數(shù),做差,然后再存儲在新列表中,循環(huán)操作,直到得到6174,程序結束。
通過三種編程方法,分別驗證,求解。
程序涉及到的是中國電子學會編程等級考試四級內(nèi)容。
即是輸入一個數(shù)字不完全相同的4位數(shù),進行驗證,看看能不能得到6174,需要幾步。
1.遞推法
輸入一個4位數(shù),但4個數(shù)字不能完全相同,將其轉換為列表,排序、連接、轉換出最大值和最小值,做差,再轉換為列表,如果不夠4位,則添加“0”,進行下一輪循環(huán),直到得到“6174”,然后輸出轉換用了多少次(圖1)。
下面是驗證“1112”的輸出結果(圖2)。
2.遞歸法
遞歸與遞推不同之處,是調(diào)用了自身,達到循環(huán)的目的。過程和方法與遞推類似。
不同的是,遞推算法中第7行的n=0,去掉了,這是因為如果加上這行,每次調(diào)用自身的時候,n都會歸0,不能計數(shù),所以必須先設置n=0,然后在自定義函數(shù)中用“global n”(圖3)。
兩種方法驗證的結果是完全一樣的。
即是驗證一定范圍內(nèi)所有數(shù)字不完全相同的4位數(shù),看看能不能得到6174,在這個范圍內(nèi)需要最多的步數(shù)是多少。
1.遞推法
通過遞推法驗證(圖4)。
在1100-1120范圍內(nèi)的驗證結果。在“1111”時提示數(shù)字完全一樣,不能驗證(圖5)。
在1000-9999范圍內(nèi)的遞推法驗證,即所有4位數(shù)的驗證結果。在數(shù)字完全一樣時,給出提示,從驗證結果看,所有不完全相同的4位數(shù),經(jīng)過運算均可以得到“6174”,運算的最多次數(shù)是“7”。
2.遞歸法
遞歸法,和遞推法一樣,也是在驗證的基礎上,驗證一定范圍內(nèi)的所有整數(shù),經(jīng)過運算是不是都能得到“6174”,并輸出最多的運算次數(shù)。不同的是遞歸是通過調(diào)用自身,達到循環(huán)的目的。
同樣,遞歸法需要將遞推算法中的n=0去掉,而在遍歷前設置n=0,然后在自定義函數(shù)中設置為“global n”。m為最大次數(shù)變量(圖6)。
在1100-1120范圍內(nèi)的驗證結果。在“1111”時提示數(shù)字完全一樣,不能驗證。驗證結果和遞推算法一樣。
在1000-9999范圍內(nèi)的遞歸法驗證,即所有4位數(shù)的驗證結果。在數(shù)字完全一樣時,給出提示,從驗證結果看,所有不完全相同的4位數(shù),經(jīng)過運算均可以得到“6174”,運算的最多次數(shù)是“7”。我們看到,兩種方法的驗證結果是完全一樣的(圖7)。
1.遞推法
將前面用遞推法的驗證和范圍的兩個程序合并在一起,但要考慮兩種方法共同調(diào)用了自定義函數(shù),所以需要將部分打印語句保留。
開始是選擇“驗證”還是“范圍”,然后進入循環(huán)和調(diào)用,輸入相關數(shù)據(jù),進行運算,如果選擇“退出”,則程序結束(圖8、圖9)。
2.遞歸法
遞歸法與遞推類似,是將前面用遞歸法的驗證和范圍的兩個程序合并在一起,同樣,開始時還是選擇“驗證”或是“范圍”,然后進入循環(huán)和調(diào)用,輸入相關數(shù)據(jù),進行運算,如果選擇“退出”,則程序結束(圖10、圖11)。
在1100-1120范圍內(nèi)的驗證結果。在“1111”時提示數(shù)字完全一樣,不能驗證。最后輸出運算的最多次數(shù)。
驗證和范圍做在了一起,下面一一講解。
1.初始化
輸入想要驗證的4位數(shù),運算次數(shù),都顯示在屏幕上, 差值會隨著運算改變,直到6174(圖12)。
2.輸入數(shù)據(jù)的檢驗
如果輸入的數(shù)值不是4位數(shù),則提示輸入(圖13)。
如果在1000-9999之間則開始運算。
3.驗證并顯示
先將輸入的數(shù)值保存在變量“差”中,然后將其每個數(shù)字添加到列表“l(fā)ist”中,再調(diào)用自定義積木,排序并求最大和最小值(圖14)。
如果差為“0”,即是數(shù)字相同時,將差設置為“6174”,因為循環(huán)的條件是差為“0”。最后提示運算了多少次。
4.自定義積木
自定義積木是為了運算的方便,也是為了程序設計方便。首先檢查列表長度,如果小于4則添加“0”補足4位,否則運算會出錯。
然后對4個數(shù)字進行從大到小排序,最后是輸入最大值和最小值,以便計算時調(diào)用。同時清空數(shù)據(jù)列表,將4個變量初始化。
1.初始化
設置需要顯示的變量,直觀,明了。
輸入范圍的開始值和結束值。最后顯示運算次數(shù)中的最大次數(shù)值。
2.驗證并顯示
在范圍內(nèi)依次取值,做驗證即可。
循環(huán)方法是次開始值增加1,依次驗證,當開始值大于結束值時,停止循環(huán)。所以循環(huán)是包括開始和結束兩個值的(圖15)。
注意幾個問題:
一是數(shù)字全部相同的,要停止運算,進入到下一個循環(huán),這里直接設置為6174(驗證時停止循環(huán)的條件);
二是保存運算次數(shù)的最大值,程序運算完,顯示出來(圖16)。
3.范圍和驗證合并
首先要將驗證和范圍都做成自定義積木,然后設計一個選擇菜單,是做一個數(shù)據(jù)驗證,還是驗證一個范圍內(nèi)的所有數(shù)據(jù),通過選擇確定,如果輸入其他則報錯。這和Python程序設計思路是一樣的。
1.UI設計
界面如圖,無須做過多修飾,組件任意組合,能完成驗證就可以(圖17)。
2.變量和初始化
設置程序運行需要的變量,將程序初始化(圖18)。
3.定義過程:建立數(shù)據(jù)列表
即可將4位數(shù)的4個數(shù)字添加到列表中,然后判斷是不是數(shù)字全部相同,如果全部相同,則做標記(圖19)。
4.定義過程:數(shù)字排序
將4個數(shù)字從大到小排序,然后輸出最大值和最小值。
5.提交
判斷輸入是否為空,是否不是4位數(shù),如果有一項不滿足,就會提示輸入有誤(圖20)。
如果輸入正確,則判斷是不是數(shù)字相同,如果數(shù)字相同,則提示不能輸入相同數(shù)字的數(shù)(圖21)。
如果數(shù)字不相同,則進入循環(huán),直到結果為6174。
首先調(diào)用數(shù)字排序,然后計算差值,將運算次數(shù)加1,顯示運算過程,同時再次調(diào)用建立數(shù)據(jù)列表,將計算出的差值依次添加到數(shù)據(jù)列表中,然后進入下一個循環(huán),直到差值為6174(圖22)。
完整的程序請在壹零社公眾號下載。
測試結果(圖23):
1.UI設計
界面設計與驗證相似,就是多加了幾個組件(圖24)。
2.初始化
其實設計時,考慮了兩種情況合并的程序(圖25)。
3.定義過程
定義過程建立數(shù)據(jù)列表和數(shù)字排序,和驗證程序的一樣。
4.提交
在一定范圍內(nèi)驗證每個4位數(shù)是不是經(jīng)過運算都能得到6174。
所以開始程序還是要檢驗輸入數(shù)據(jù)的正確性,然后進行循環(huán),從開始值依次加1到結束值,一一驗證。最后顯示運算的最大次數(shù),與Python和Scratch相同。
驗證過程基本和之前的一樣。首先顯示當前驗證的值,然后調(diào)用“建立數(shù)據(jù)列表”,如果數(shù)字相同則提示(圖26)。
否則就循環(huán)執(zhí)行驗證,直到差值為“6174”,同時顯示本次運算的次數(shù)。如果運算次數(shù)大于最大次數(shù),則將最大次數(shù)賦值為次數(shù)。
完整的程序請在壹零社公眾號下載。
測試結果(圖27):
1.UI設計
界面設計與“范圍”相同,本例在最初設計時,即考慮了合并狀態(tài)。
2.變量和初始化
這個與驗證時一樣。
3.定義過程
這個也是一樣的,建立數(shù)據(jù)列表和數(shù)字排序兩個過程。
4.驗證
驗證4位數(shù)時,點擊按鈕,即設置初始化值。當前使用的按鈕功能,會顯示為紅色背景(圖28)。
5.范圍
需要驗證一定范圍內(nèi)的所有4位數(shù)時,點擊按鈕,即設置初始化值。當前使用的按鈕功能,會顯示為紅色背景。
6.提交
提交按鈕,要先判斷是驗證狀態(tài),還是范圍狀態(tài),需要判斷驗證標記。如果驗證標記為“真”,則進行驗證界面,否則進入范圍驗證界面,兩個程序如前(圖29)。
由于前面分別測試過,所以這里不再測試。
三種方法的測試速度都非常快。由于軟件的局限,設計思路稍有不同,但均完成了驗證任務。
三種程序也可以進行改進,比如,每一步都是自己來完成計算,即輸入一個數(shù)后,自己取最大和最小值,再做差,依次運算來驗證?;蚴请S時查看程序的驗證過程。這里給出一個簡單的Python程序示例,自定義函數(shù)與遞推的驗證程序一樣。運行結果如下(圖30)。
如果輸入有誤,7次之內(nèi)沒有驗證出來,則提示輸入有錯誤,沒有完成驗證。
本文是我自己的研究過程和心得,有不妥之處,請各位老師和同學斧正!