您好,登錄后才能下訂單哦!
這篇文章主要介紹Python秒算24點如何實現(xiàn),文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!
什么是24點
我們先來約定下老王和他媳婦玩的24點規(guī)則:給定4個任意數(shù)字(0-9),然后通過+,-,*,/,將這4個數(shù)字計算出24。
小時候玩的都是這個規(guī)則,長大了才有根號,才有各種莫名其妙的高級算法,不好玩了,因為我不會。
可能有人會覺得很簡單,但是真的簡單嗎?
比如:
8,3,3,3
7,3,3,3
你能一眼看出來答案嗎?好像真的可以……
大致思路
這樣想,將四個數(shù)字進(jìn)行全排列,在他們之間添加運算符號。
運算符我們需要進(jìn)行排列組合,因為只有四個數(shù)字,所以只需要三個運算符,而且算法符可能會重復(fù),比如三個都是+。
再遍歷四個數(shù)字的全排列,對每一組數(shù)字而言,遍歷所有組合的操作符。最后將數(shù)字和操作符進(jìn)行拼接運算,就可以得到最終結(jié)果了。
演示環(huán)境
操作系統(tǒng):windows10
python版本:python 3.7
代碼編輯器:pycharm 2018.2
使用模塊:math,itertools, collections.abc
具體代碼
1、首先我們對所有數(shù)字進(jìn)行去全排列,這里我們使用 itertools.permutations 來幫助我們完成。
iertools.permutations 用法演示
from itertools import permutations data_list = permutations([1,2,3,4],2) for data in data_list: print(data)
結(jié)果顯示
(1, 2) (1, 3) (1, 4) (2, 1) (2, 3) (2, 4) (3, 1) (3, 2) (3, 4) (4, 1) (4, 2) (4, 3)
permutations 第一個參數(shù)是接收一個課迭代的對象,第二個參數(shù)指定每次排列時從課迭代對象中選著幾個字符進(jìn)行排列。也可以不傳入第二個參數(shù),那么默認(rèn)就是可迭代對象的長度。并且返回一個生成器。
所以我們需要對所有數(shù)字進(jìn)行全排列,就可以像下面這樣寫:
def get_all_data_sequence(data_iter): return permutations(data_iter)
2、然后我們需要拿到所有的操作運算符的所有組合方式。這里我們就會使用 itertools.product 函數(shù)了。
itertools.product 用法演示
from itertools import product sequence1 = product('ABCD','xy') sequence2 = product([0,1],repeat=3) for sequence in sequence1: print(sequence) print('-'*30) for sequence in sequence2: print(sequence)
結(jié)果顯示
('A','x') ('A','y') ('B','x') ('B','y') ('C','x') ('C','y') ('D','x') ('D','y') ------------------------------ (0, 0, 0) (0, 0, 1) (0, 1, 0) (0, 1, 1) (1, 0, 0) (1, 0, 1) (1, 1, 0) (1, 1, 1)
itertools.product,返回傳入所有序列中笛卡爾積的元祖,repeat參數(shù)表示傳入序列的重復(fù)次數(shù)。返回的是一個生成器。
那么獲取所有的操作運算符就可以通過這個函數(shù)來獲取了
def get_all_operations_sequence(): operations = ['+','-','*','/'] return product(operations,repeat=3)
3、現(xiàn)在我們已經(jīng)拿到了所有可能組合的操作符和數(shù)字了,接下來就需要對他們進(jìn)行拼接了。然后執(zhí)行運算。
這一步操作我們會用到 itertools.zip_longest() 和 itertools.chain.form_iterable() 函數(shù)。
itertools.zip_longest() 用法演示
data = zip_longest([1,2,3,4],['*','-','+'],fillvalue='') for value in data: print(value)
結(jié)果顯示
(1, '*') (2, '-') (3, '+') (4, '')
zip_longest() 其實和 python 內(nèi)置的 zip() 函數(shù)用法差不多,只是 zip_longest 是以最長的一個序列為基準(zhǔn),缺失值就使用 fillvalue 參數(shù)的值進(jìn)行填充
itertools.chain.form_iterable() 用法演示
data = zip_longest([1,2,3,4],['*','-','+'],fillvalue='') data_chain = chain.from_iterable(data) for value in data_chain: print(value)
結(jié)果顯示
1 * 2 - 3 + 4
這里的data是什么樣的大家知道了吧,然后我們將data傳入 chain.form_iterable() 中,它就能將里面的值依次拿出來。
了解了這兩個函數(shù)之后,那么我們就可以開始拼接數(shù)字和操作運算符了。
def calculate(self): ''' 計算值,返回對應(yīng)的表達(dá)式和值 :return: ''' for data_sequence in get_all_data_sequence(): operation_sequences = get_all_operation_sequence() for operation_sequence in operation_sequences: value = zip_longest(data_sequence, operation_sequence, fillvalue='') value_chain = chain.from_iterable(value) calculate_str = '' # 對得到的字符進(jìn)行拼接成為表達(dá)式 calculate_str for _ in value_chain: calculate_str += _ try: result = eval(calculate_str # 處理被除數(shù)可能為零的情況,然后就直接跳過這次循環(huán) except ZeroDivisionError: continue if math.isclose(result, 24): return calculate_str,result return None,None
代碼分析
1、eval() 函數(shù),接受一個字符串,能讓這個字符串當(dāng)成 python 代碼運行,返回運行的結(jié)果。
2、math.isclose():為什么這里需要使用 math.isclose() ,而不是直接使用==運算符呢?這是因為最后算出來的表達(dá)式可能有精度問題,例如23.9...或者24.0...等數(shù)字,所以我們就需要使用math.isclose()函數(shù)來幫助我們判斷兩個數(shù)字是否相等了,這個函數(shù)就有一個精度范圍。這樣出現(xiàn)上面情況的時候,我們也能匹配得到條件了。
我們運行代碼,然后測試代碼是否能達(dá)到我們的需求。
首先我們測試1,2,3,4四個數(shù)字,
程序出來了結(jié)果 1*2*3*4 24
看來好像我們寫的代碼是正確的
我們再來測試一組數(shù)據(jù)8,8,3,3.
嗯?我們并沒有得到結(jié)果?這四個數(shù)字不能運算出24嗎?
8 / ( 3 - 8 / 3 ) 這樣組合可以吧,為什么沒有算出來這種結(jié)果呢?
這是因為我們沒有考慮括號的原因。括號是可以改變運算優(yōu)先級的。所以我們得把括號考慮進(jìn)去。
那么想一下括號最多可以有幾個呢?怎樣給我們的表達(dá)式添加括號呢?
在4個數(shù)字的運算中,括號最多只能有三個。
并且,在這里,我們使用一種簡單的方法添加括號,我們把所有可能出現(xiàn)括號的情況全部羅列出來,然后在將得到的運算表達(dá)式拼接進(jìn)去。
可能大家會覺得羅列出所有括號出現(xiàn)的情況不現(xiàn)實,因為有很多情況
其實不然,當(dāng)我們?nèi)チ_列的時候,你就會發(fā)現(xiàn),只有11種情況。
FORM_STRS = [ # 數(shù)字 運算符 數(shù)字 運算符 數(shù)字 運算符 數(shù)字 # 一個括號 的情況 '(%s %s %s) %s %s %s %s', '(%s %s %s %s %s) %s %s', '(%s %s %s %s %s %s %s)', '%s %s (%s %s %s) %s %s', '%s %s (%s %s %s %s %s)', '%s %s %s %s (%s %s %s)', # 兩個括號 的情況 '(%s %s %s) %s (%s %s %s)', '( (%s %s %s) %s %s) %s %s', '( %s %s (%s %s %s)) %s %s', '%s %s ((%s %s %s) %s %s)', '%s %s (%s %s (%s %s %s))', # 三個括號是重復(fù)的,就不用羅列出來了 ]
然后我們對得到的表達(dá)式在進(jìn)行遍歷拼接,然后我們再運算表達(dá)式。
這樣我們就能得出正確的結(jié)果了。
以上是“Python秒算24點如何實現(xiàn)”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。