使用python?itertools實(shí)現(xiàn)計(jì)算雙十一滿減湊單
雙十一
湊單問(wèn)題
一年一度的雙十一又到了,在這樣一個(gè)日子中,可能遇到一些問(wèn)題,首先是“湊單”問(wèn)題。比如說(shuō),在電商活動(dòng)中,經(jīng)常會(huì)有“滿減”,例如,“滿200,減30”,在這樣的情況下,我們需要達(dá)到目標(biāo),或超過(guò)目標(biāo)(因?yàn)?,未達(dá)到目標(biāo),是不能進(jìn)行滿減的)。
很顯然,如果我們買200元的物品,需要付出170元(相當(dāng)于85折),而買300元的東西,需要付出270元(相當(dāng)于9折)。也就是說(shuō),我們需要找到一個(gè)或多個(gè)商品組合,使其價(jià)格總和盡可能接近目標(biāo)金額,且超過(guò)目標(biāo)金額。
積分問(wèn)題
另外一個(gè)常見的問(wèn)題,是“積分兌換“問(wèn)題,比如說(shuō),賬號(hào)中有1000積分,可以兌換若干樣?xùn)|西,在這樣的情況下,我們需要盡可能的接近目標(biāo),但是不能超過(guò)目標(biāo)(因?yàn)?,超過(guò)積分的行為是不被允許的)。
很顯然,積分通常有期限,剩余的積分往往不能發(fā)揮任何作用。也就是說(shuō),我們需要找到一個(gè)或多個(gè)商品組合,使其價(jià)格總和盡可能接近目標(biāo)積分,但不超過(guò)目標(biāo)積分。
問(wèn)題解決
解決湊單問(wèn)題
解決方法:
1.假如一個(gè)商品列表prices,目標(biāo)金額target,并且定義一個(gè)變量min_excess,用于記錄最小的超出金額差值,best_combination用于存儲(chǔ)最優(yōu)組合。
2.從prices中選擇每一個(gè)商品,計(jì)算商品組合的總價(jià)格,如果價(jià)格超過(guò)了target,檢查是否是當(dāng)前最接近的組合??們r(jià)格如果未超過(guò)target,那么繼續(xù)添加其他商品。
3.最終,得到最優(yōu)組合best_combination。
from itertools import combinations def find_best_combination(prices, target): best_combination = None min_excess = float("inf") for i in range(1, len(prices) + 1): for comb in combinations(prices, i): total_price = sum(comb) if total_price >= target and (total_price - target) < min_excess: min_excess = total_price - target best_combination = comb return best_combination, sum(best_combination) if best_combination else 0 prices = [66, 33, 24, 89, 77] target = 200 best_combination, best_price = find_best_combination(prices, target) print(f"最優(yōu)組合: {best_combination}, 總價(jià): {best_price}")
這里,我們使用了一個(gè)工具,itertools庫(kù)中的combinations,該函數(shù)的作用是,生成不重復(fù)的元素組合。
# 以[1, 2, 3]為例 # 此時(shí)的結(jié)果為:[(1,), (2,), (3,)] print(list(combinations([1, 2, 3], 1))) # 此時(shí)的結(jié)果為:[(1, 2), (1, 3), (2, 3)] print(list(combinations([1, 2, 3], 2))) # 此時(shí)的結(jié)果為:[(1, 2, 3)] print(list(combinations([1, 2, 3], 3)))
解決積分兌換
與湊單問(wèn)題類似,其實(shí)只需要不超過(guò)的最接近值即可。
from itertools import combinations def find_best_combination(prices, target): best_combination = None max_total = 0 for i in range(1, len(prices) + 1): for comb in combinations(prices, i): total_price = sum(comb) if total_price <= target and total_price > max_total: max_total = total_price best_combination = comb return best_combination, max_total prices = [66, 33, 24, 89, 77] target = 200 best_combination, best_price = find_best_combination(prices, target) print(f"最優(yōu)組合: {best_combination}, 總積分: {best_price}")
保存多個(gè)結(jié)果
有的時(shí)候,雖然我們得到了最佳結(jié)果,但是,最佳結(jié)果并不一定是我們希望的。比如說(shuō),最佳結(jié)果中,買到的商品,可能并不是我們最滿意的,因此,保存多個(gè)組合方案,可以提供多種參考。
對(duì)于湊單問(wèn)題:
from itertools import combinations import heapq def find_top_combinations(prices, target, top_n=5): heap = [] for i in range(1, len(prices) + 1): for comb in combinations(prices, i): total_price = sum(comb) if total_price >= target: excess = total_price - target heapq.heappush(heap, (-excess, total_price, comb)) if len(heap) > top_n: heapq.heappop(heap) top_combinations = sorted(heap, key=lambda x: -x[0]) return [(comb[2], comb[1]) for comb in top_combinations] prices = [66, 33, 24, 89, 77] target = 200 top_n = 5 top_combinations = find_top_combinations(prices, target, top_n=top_n) print(f"最優(yōu)的{top_n}種組合及其總價(jià):") for i, (combination, total_price) in enumerate(top_combinations, 1): print(f"組合 {i}: {combination}, 總價(jià): {total_price}")
此時(shí),可以看到結(jié)果顯示為:
最優(yōu)的5種組合及其總價(jià):
組合 1: (66, 33, 24, 77), 總價(jià): 200
組合 2: (66, 33, 24, 89), 總價(jià): 212
組合 3: (33, 24, 89, 77), 總價(jià): 223
組合 4: (66, 89, 77), 總價(jià): 232
組合 5: (66, 24, 89, 77), 總價(jià): 256
對(duì)于積分兌換問(wèn)題:
from itertools import combinations import heapq def find_top_combinations(prices, target, top_n=5): top_combinations = [] for i in range(1, len(prices) + 1): for comb in combinations(prices, i): total_price = sum(comb) if total_price <= target: if len(top_combinations) < top_n: heapq.heappush(top_combinations, (total_price, comb)) else: if total_price > top_combinations[0][0]: heapq.heappushpop(top_combinations, (total_price, comb)) top_combinations.sort(reverse=True, key=lambda x: x[0]) return [(comb[1], comb[0]) for comb in top_combinations] prices = [66, 33, 24, 89, 77] target = 200 top_n = 5 top_combinations = find_top_combinations(prices, target, top_n=top_n) print(f"最優(yōu)的{top_n}種組合及其總價(jià):") for i, (combination, total_price) in enumerate(top_combinations, 1): print(f"組合 {i}: {combination}, 總價(jià): {total_price}")
此刻可以看到結(jié)果顯示為:
最優(yōu)的5種組合及其總價(jià):
組合 1: (66, 33, 24, 77), 總價(jià): 200
組合 2: (33, 89, 77), 總價(jià): 199
組合 3: (24, 89, 77), 總價(jià): 190
組合 4: (66, 33, 89), 總價(jià): 188
組合 5: (66, 24, 89), 總價(jià): 179
到此這篇關(guān)于使用python itertools實(shí)現(xiàn)計(jì)算雙十一滿減湊單的文章就介紹到這了,更多相關(guān)python計(jì)算滿減湊單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python統(tǒng)計(jì)純文本文件中英文單詞出現(xiàn)個(gè)數(shù)的方法總結(jié)【測(cè)試可用】
這篇文章主要介紹了Python統(tǒng)計(jì)純文本文件中英文單詞出現(xiàn)個(gè)數(shù)的方法,結(jié)合實(shí)例形式總結(jié)分析了Python針對(duì)文本文件的讀取,以及統(tǒng)計(jì)文本文件中英文單詞個(gè)數(shù)的4種常用操作技巧,需要的朋友可以參考下2018-07-07Python分聃?之?dāng)?shù)字雨加入潘周聃運(yùn)動(dòng)曲線的詳細(xì)過(guò)程
相信各位同學(xué)最近一定被潘周聃刷屏和洗腦了,互聯(lián)網(wǎng)上也出現(xiàn)了這種各樣的模仿者,下面通過(guò)本文給大家分享Python分聃之?dāng)?shù)字雨加入潘周聃運(yùn)動(dòng)曲線,需要的朋友可以參考下2022-05-05python實(shí)現(xiàn)簡(jiǎn)單的飛機(jī)大戰(zhàn)游戲
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡(jiǎn)單的飛機(jī)大戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05使用Python實(shí)現(xiàn)插入100萬(wàn)條數(shù)據(jù)到MySQL數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)插入100萬(wàn)條數(shù)據(jù)到MySQL數(shù)據(jù)庫(kù),文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下2024-04-04Python+tkinter自定義實(shí)現(xiàn)文件選擇按鈕
這篇文章主要為大家詳細(xì)介紹了如何利用Python和tkinter自定義實(shí)現(xiàn)簡(jiǎn)單的文件選擇按鈕和顏色選擇按鈕,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10Python 實(shí)現(xiàn)兩個(gè)服務(wù)器之間文件的上傳方法
今天小編就為大家分享一篇Python 實(shí)現(xiàn)兩個(gè)服務(wù)器之間文件的上傳方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-02-02