陳凱
在學習程序語言時,初學者常會遇見這樣的任務:輸入三個數(shù)字,將它們從小到大排好序。圖1是用Python代碼實現(xiàn)此任務的例子。
任務目標很明確,實現(xiàn)任務的程序代碼量也不多,然而,分支嵌套分支,其中再嵌套分支的結構有可能把人弄暈,雖然其中涉及的邏輯推理不難,但落實到程序語言上,想要把邏輯關系理順,也不是一時半會兒的事情。乍看上去,這種通過多層分支嵌套解決問題的方式很“計算機”,距離人腦直觀判別數(shù)字大小的方法很遠,人類在面對三個不同大小的數(shù)字時,難道不是直觀看上一眼后,就能瞬間把順序排列好嗎?
但只要多想一點,就會發(fā)現(xiàn),認為“多層嵌套分支”很“計算機”的想法,未必是事實,因為在某些特殊的場景中,人類的確是需要以這種邏輯推理的方式來判別三個對象值的大小的。舉例說,某任務要求用一個電壓比較器比較三個觸點電壓的大小,因為電壓比較器每次只能比較兩個觸點,所以就要利用類似分支嵌套的方式,來獲知三個觸點的電壓相對大小的情況。
若再仔細思考,就會注意到,在各種不同的場景任務中,人其實是使用各種不同的方法來給對象值的大小進行排序的,而其中應用的靈活程度,恐怕連使用者自己也不知道。但借助算法的模擬,卻反而能揭示出思維運作中的奧秘,以下再試舉幾例。
● 三棵白菜重量的排序
沒有計量工具時,怎么快速估量出三棵白菜的重量并排序呢?若重量差異明顯,那么用手掂一掂就可以了。但是白菜有三棵,手只有兩只,怎么辦?這個問題并不難辦,不妨先找出最輕(或最重)的那一棵白菜。掂一棵白菜,記住它大概的重量,再掂另一棵,若它更輕(或更重),則記住它,否則就把它放到一邊去,然后再掂最后一棵。用這樣的辦法找出最輕(或最重)的白菜,然后把它放到第一位(或最后一位)。接下來就簡單了,只要比較剩下的兩棵白菜的重量就可以了。
試著用程序代碼(如圖2)模擬這樣的思維方式:把三個數(shù)字放進列表,用tmp變量代表人頭腦中臨時存儲的數(shù)據(jù),先找出最小數(shù),然后將其從列表中刪除,接著比較剩下的兩個數(shù)字即可。
● 三個生肖先后的排序
如果有人問馬、雞、兔這三個生肖哪個在先哪個在后,不是所有人都能第一時間回答上來,然而十二生肖全體的順序,大部分人都能通過口訣背出來:鼠?;⑼谬埳唏R羊猴雞狗豬。在背誦口訣時,特定生肖出現(xiàn)的次序自然而然顯現(xiàn)了出來,所以在比較生肖大小的時候,往往要背一遍生肖口訣,哪個生肖先出現(xiàn),自然就排在前面——實際上,筆者每次都是這么做的。代碼如圖3所示。這段程序代碼的作用,就是觀察哪個數(shù)字會先在數(shù)字的列表中“涌現(xiàn)”出來,其運行結果如圖4所示。
● 三張撲克大小的排序
在整理撲克牌的時候,假設只考慮從小到大排列,人們會采用什么樣的方法呢?
有兩種比較常用的辦法,一種是,看見相鄰的撲克牌,如果順序不對,就把它們換過來。反復執(zhí)行此過程,直到所有牌排列整齊。這其實就是冒泡排序的思想了,只是人在整理撲克牌時,并不嚴格遵守“相鄰”這一規(guī)則,交換次序的對象也是隨性而為。
用冒泡排序的方法給三個數(shù)字排序,代碼十分簡單,如圖5所示。
人們有時也使用另一種方法,因為數(shù)字從小到大排列完成后,它們所處的位置是固定的,“A”必然是在1號位,“2”必然是在2號位,所以只要抽取撲克牌,直接把它放到應處的位置上就可以了。用程序代碼(如圖6、圖7)模擬這種方法,甚至連分支結構都不需要了,這難免讓人懷疑,這真的算是排過序了嗎?
從上面的各種例子能看出,僅就三個數(shù)字從小到大排列這一任務,有著許多不同的程序設計手段,足以展現(xiàn)出人的思維的變化多端。
當前,“計算思維”一詞頗為熱門,本文給出了一條比較獨特的研究路徑,即將計算本身作為一種工具來回溯人的思維,借助不同的計算方式,來模擬出人在不同場景和任務中的思維方式。
人的思維本身隱藏在頭腦之中,難以直接觀察、檢驗和描述,雖然當前人們主觀上認為,這種模仿尚不能揭示人類思維本身(此處不考慮持強人工智能觀點的學者對未來技術發(fā)展的假想),但人們往往能夠判別出,某些計算機程序的運作過程更接近于哪些場景中人類完成任務的模式。即便像枚舉算法,比如“在三位數(shù)中找出所有能被13整除的數(shù)字”這樣的任務,乍看上去十分機械無趣,但枚舉此事本身,無論是確定檢查范圍、匹配一致性,還是就對象進行分類(分成滿足條件或不滿足條件兩類),都需要用到抽象的邏輯推理。這方面的思維能力,甚至不能說這是人類專屬的能力,有一些抽象的邏輯推理能力在鳥類和哺乳動物的行為實驗中得到了驗證??梢?,即便是那種很機械、很計算機式的工作過程,也與動物或人的思維方式密切相關。