王洪波 山東省榮成石島實驗中學
董俊 安徽省阜陽市第三中學
生活中的算法無處不在,如去醫院要取號排隊、調查問卷要分類篩選、家務勞動要統籌分治……生活中的算法也許與計算機的算法并不一致,但我們不能忽視信息科技對生活方式的革新,將生活中的思想方法與算法結合,對算法的學習也大有意義。
撲克中也蘊含著算法思想。在玩撲克時,通常要先洗牌,將牌打亂成無序狀態,然后每個人輪流摸牌,為了方便出牌,每摸取一張牌,我們都會將其插入到手中已排好順序的牌中,最終一堆無序的牌變成了我們每個人手中有序的牌,這是如何做到的呢?每摸一張牌,比手中的牌大就放后邊,小就放前邊;當手中的牌多起來,只需要將其插入到合適的位置即可,這就是插入排序算法的思想及其運用。
插入排序這的確是算法,程序設計中的插入排序跟玩撲克的排序方式是一模一樣的,現在一起來回顧摸牌的過程,體驗插入排序的原理:在開始抓牌之前,我們手中并沒有牌,當摸取到第一張牌時,手中的牌就已經有了順序。當摸取第二張牌時,一般習慣于按升序的方式來排列,如果這張牌比第一張小,就要放在前邊,如果大就放在后邊。例如,第一張是4,第二張是5,順序就是4,5。第三張、第四張、第五張……以后的牌越來越多,要比較的次數就更多。假如你現在手中有4張排好序的牌(如表1),現在又摸了一張7,如何將這張牌插入到有序的序列中呢?我們可以將這張牌與最后一張比較,如果這張牌比10大,就直接放在10之后,如果小就與10之前的5比較,如果比5大就插到5之后(如表2)。

表1 已排好序的牌

表2 將牌7插入到有序序列中
在理解了插入排序思想并運用自如之后,代碼就水到渠成了(如下頁圖1)。

圖1
可見,如果用生活中貼近計算機的算法案例讓學生在玩中學、學中玩,往往會取得事半功倍的效果。
街上經常會見到一些攤位寫著“不說話,猜你的姓氏,不準不要錢”“黃雀算命”等字樣,這些看似輸贏都是靠運氣的游戲,吸引了不少人。下面筆者就以摸球游戲為例,探究這種街頭游戲的秘密。
不透明箱子中有24顆小球(紅色、黃色、藍色各8顆),玩家每次抽取12顆小球,然后根據下頁表3獎勵金額情況,查看獲獎金額。例如,抽到5個紅球、7個黃球、0個籃球,就是750組合,獎勵給玩家50元。

表3 小球數量的組合及獎勵金額
只有一種“543”的組合需要玩家付給攤主錢,其余都是獎勵,一元錢可以玩5次,成本又很低,這就吸引了很多人參與游戲。
先嘗試一次2元的,摸10次看看輸贏情況。我們沒有這套裝備,可以用計算機程序來模擬一下這個過程,如下頁圖2所示。

圖2
用random隨機數的方式模擬隨機抽球的過程,a1,a2,a3表示每局游戲抽取三種顏色小球的數量,運行程序看看結果(如圖3)。

圖3
程序運行兩次,其計算結果如下。第一次:1+1+1-20+1+1+1+1-20+1=-32;第二次:1+1-20-20+1-20+1-20-20+1=-95。
看到前面的游戲體驗結果,發現兩次游戲玩家都沒有賺到錢,反而賠了不少錢,為什么呢?可以先思考如下兩個問題:①24顆球抽取12顆有多少種組合情況?②為什么將543的組合設置為罰錢的組合,將840設置為最高獎勵組合?先來回答第一個問題,按照程序中a1,a2,a3可能出現的結果,都在圖2中有所體現,不過每種組合都可能包含6種情況,如543的組合包含了345,354,453,435,543,534這六種情況。再思考第二個問題,我們不妨大膽猜測是因為543組合出現的概率大,840組合出現的概率小。這是大多數人都能想到的猜測,那么它們的概率大概是多少呢?我們可以把這個解密原理的關鍵問題抽象出來,即轉化為計算游戲中543和840出現的概率問題。
(1)探究問題。計算摸球游戲出現543組合的概率。
(2)算法分析。參考數學中計算拋一枚硬幣正面朝上的概率,進行100次實驗,統計正面朝上的次數,然后計算出正面朝上的頻率。枚舉n次實驗,其中正面朝上的次數為r,則正面朝上的概率約為r/n,這里用到的就是枚舉的算法思想。我們同樣可以用這種算法估算出摸球游戲中543組合和840組合出現的概率。也就是枚舉一定數量的實驗結果,每次實驗中統計出543或840組合出現的次數,具體算法流程描述如下:①設置枚舉的樣本總量n。②隨機抽取12個小球。③統計小球的某種組合情況r。④重復第二步操作。⑤計算r/n的值。
(3)驗證結果。對于a1,a2,a3是543的組合有6種情況如何判斷呢?當然,枚舉這6種情況是一種辦法,但是條件會比較多,代碼看起來會比較繁雜。另一種方法就是使用Python中的成員運算符“in”,只需要判斷if(3 in [a1,a2,a3]and 4 in [a1,a2,a3] and 5 in[a1,a2,a3])是否成立即可。當然,由于每次只抽取12顆球,a1+a2+a3的和為12是固定的,所以條件也可以優化為只判斷兩個數字即可,也就是if(3 in [a1,a2,a3] and 4 in[a1,a2,a3]),參考代碼如圖4所示。

圖4
運行程序記錄結果如表4所示。

表4 運行程序
(4)得出結論。543組合出現的概率約是49%,也就是每兩局游戲就可能會出現一次543,840出現的概率約是0.02%,從數學的角度去看原來攤主做的是穩賺不賠的買賣啊!
蒼山點題
我們通過嘗試從深度學習的角度剝開編程教學的堅硬果殼,目的是要在學習中看到編程思想的“果肉”,體會編程學習的滋味,吸取算法思想的營養。承接上一期解碼,我們從編程知識的學習、算法結構的認知等方面去觀察如何更有效地開展學習。一方面尋找算法應用的本質,即運用算法來處理現實問題;另一方面尋找生活算法與計算機算法的契合點,就是將生活算法與計算機算法進行對照學習,而不是無聯系地各說各話。
第一篇文章,兩位教師從一線教學進行觀察與創新,力圖讓算法應用于生活,學會怎么選擇合適的算法來服務生活。第一部分,候老師是以在教學視導中聽的一節公開課《用選擇結構程序做出判斷》為基礎,課中授課選用了實現送餐機器人功能的項目,讓學生通過編程實現機器人依據學生在食堂點餐來配送相應的飯菜,探討如何從讓算法在生活中更真實、可用的角度進行改進,力求解決實際問題,體現算法意義;第二部分,吳老師從“基于‘用戶登錄’開展深度學習”著手,將真實軟件用戶界面設計與功能設計相結合,把算法與信息系統進行融合學習,一步步提高加密算法的應用,讓算法學習提高到了系統設計,意義重大。
第二篇文章,兩位教師從一線教學中展開實踐與總結,嘗試讓生活算法與計算機算法相結合,以算法的視角分析問題、研究問題。第一部分,王老師以“撲克中的‘插入排序’算法思想”為例,嘗試用通俗的撲克牌整理為例,通過程序來模擬插牌過程,對問題進行了分解、分析與模擬,讓插入排序得到了清晰的呈現,生動有趣;第二部分,董老師用“枚舉”算法解密街頭騙術,對隨機組合進行基于枚舉算法的數據研究,對概率、組合等數學知識與算法也進行了良好的融合,這是一個跨學科學習的良好體驗,也是數據研究的正確策略,值得學習與借鑒。
可以說,編程教學本身是非常重要的,我們只有深入到算法中去,深入到計算思維中,才能讓編程不是死學知識,而是面向生活、面向應用、面向研究。在編程過程中體現出算法思想與計算思維,這是我們未來不斷努力的方向。