背景
如果說PHP是世界上最美麗的語言,那么python一定是最簡單,最強大,最容易的語言!重點是,這兩門語言我都不懂!隨着人工智能領域的風生水起,python的熱度也是持續飆升,作為當下最熱門的語言,怎么能不讓人心動呢!
趁着過年這段時間,補充了一下python相關的基礎知識,可以說是簡單的入門了,如果有一點代碼基礎,入門python可以說是非常容易,但是,並非入門了python就意味着你可以拿着簡歷到處招搖撞騙了,入門雖然容易,但是還需要很多項目實戰,類庫的學習沉淀,你才可以在python的世界里面風風火火玩起來!
早兩天看到了這樣一道推理題,可以稱得上是變態。題目如下:

第一題就足夠虎住大部分人,仔細分析,這些題目有一個特點,信息量大,計算量大。這種任務,給計算機來做事最合適不過的了!那就拿python來練練手吧!
項目分析
任務共分為10道題,有10個答案,每道題之間有一定的聯系,而且關系也比較復雜,但比較明確。方案分為兩種:
-
模擬法:即模擬人的解題行為,找到10題中的突破口,嘗試推出下一題,並以此為跳板,推出下一題,一旦出錯,從頭開始嘗試,直到推出所有答案
-
窮舉法:這是一種非常規的解題方法,目的是利用計算機的計算優勢,枚舉可能的所有答案組合,逐個驗證每題的正確性,直到所有題目都驗證通過。
很顯然,窮舉法的復雜度要明顯低於模擬法,但是執行時間要遠高於模擬法。但模擬法的業務復雜度較窮舉法要高很多,開發難度較大。考慮到本題的特性,10道題,每題4個選項,復雜度最大為4的10次方共計1,048,576次,對於計算機來說,最大執行時間可以控制在10分鍾之內。
設計
本次聯系共需要以下三個模塊,結構如下圖:
-
數據器 - 用來組織生成各道題的答案組合
-
過濾器 - 在對數據進行驗證之前,進行必要的處理
-
驗證器 - 驗證每組答案的正確性
數據構造
數據器完成了數據的管理功能,目的是把10道題和ABCD這4個選項進行一次排列組合,共計4^10=1,048,576個,我們采用了類進制法來進行全排列的處理。即一個10位的序列,從AAAAAAAAAA開始,到DDDDDDDDDD結束,從第一位開始每次加1,每位逢D+1進一位,本位變A,則可以動態生成全排列序列。由於要進行加1運算,因此我們這里進行一些簡單的編碼,即將ABCD分別用數字1234表示,方便后續的算術運算,代碼如下:
| def increase(index): if(index == 10): return False r[index] += 1 if(r[index] == 5): r[index] = 1 return increase(index+1) returnTrue |
當然,我們也會直觀的想到先將所有的數據都先生成,存儲起來,最開始我也是這么做的,直觀的使用list存儲了結果,最終內存不夠了,而且生成這部分數據本身就很慢,再仔細分析,雖然我們的時間復雜度為4^10,但是,我們的最終答案一定不會到DDDDDDDDDD,所以,實際執行時間肯定要小於這個時間,因此,如果加入這種處理之后,實際執行時間必定大於最大執行時間,因此這種方案最終被優化掉了。生成數據采用的是完全不同的另外一種思路,有興趣可以參考:
| rlist = [] def createResult(): for i in range(10): if(len(rlist) == 0): ro = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] for j in range(4): ro = copy.deepcopy(ro) ro[i] = j+1 rlist.append(ro) else: for ro in rlist: for j in range(4): ro = copy.deepcopy(ro) if(ro[i] == j+1): continue ro[i] = j+1 rlist.append(ro) return rlist |
上例中的rlist換成文件讀取寫入效果可能會好點,由於是遺棄代碼,這里不再詳細討論。
數據存儲
不得不承認,python中目前感覺最好用的數據格式莫過於list了,無類型加上索引操作,萬物皆對象的想法,真的是讓list變得無所不能!我們關於10道題的答案建立了一個長度為10的列表來存儲答案組,后續所有的驗證即更新全部都在這個列表中進行,在各個模塊之間起到橋梁的作用。
過濾器
過濾器在本次項目中並非必選項,加這個模塊只是為了代碼的結構清晰,功能明確。我們針對不同的題目可以設置不同的過濾器,如第三題,我們要驗證每個選項之前,我們需要先確定,選項之間的關系,這里我們設置一個過濾器,免得第三題的驗證器內容過於臃腫,代碼如下:
| def q3_1(index): indexlist = [2,5,1,3] for i in indexlist: if(index == i): continue elif(r[index] == r[i]): return False return True |
驗證器
驗證器的目的為驗證生成的答案是否全部都為正確答案,他的功能是根據不同的題目不同的,因此,必須為每一道題設置一個驗證器,但也有例外,比如第一題,無論我們的答案是什么,這道題永遠都是對的,因此,第一題不需要驗證器。我們以第二題為例,先看代碼:
| def q2(): if(r[1] == 1 and r[4] == 3): return True elif(r[1] == 2 and r[4] == 4): return True elif(r[1] == 3 and r[4] == 1): return True elif(r[1] == 4 and r[4] == 2): returnTrue else: return False |
第二題的答案的意思大概是這樣的:如果第二題的答案是A(即r[1]=1)時,第五題的答案為C(即r[4]=3),如果如果第二題的答案是B(即r[1]=2)時,第五題的答案為D(即r[4]=4),以此類推。故當我們可以通過判斷第二題與第五題的答案關系來驗證第二題的答案是否正確,如果有一項不滿足,就驗證失敗。即答案錯誤
后記
到這里,我們的這次實戰也就告一段落了。通過本次實戰,鞏固了這段時間學習的大部分知識,同時也發現了很多python的優點,感觸良多:
-
python更像是為解決問題設計的
大部分程序語言都是開發者根據使用者提出的需求來完成編碼,交付項目,然后讓使用者使用這套工具來完成他們的任務,任何一段代碼,如果不使用幾次,我們總感覺缺少點什么。但是在使用python時完全沒有這樣的感覺,哪怕是刪掉了,重新寫一套,也很快很容易。
- 在這個各種平台,開源類庫橫行的年代,基本功還是要扎實
別人給你的只能是鍋,鏟子,食物和調料。而如何做出美味的飯菜,還得靠你自己去搭配。編程思想,實現方案才是各種編程語言通用的東西,而這些也是一個IT從業人員最寶貴的財富,在遇到問題的時候,多一套方案,你就離成功更近一步!
總之,代碼的世界就是要多練多練再多練,多想多想再多想!同時也歡迎大家關注我的微信公眾號:毛毛蟲的爛筆頭,一起交流,一起成長!

