Python返回适合设置参数的项目列表

问题描述

我在将返回的解决方案正确装箱到min_cals时遇到一些困难。

menu = [
    {'name':'Cheese Pizza Slice','calories': 700,'cost': 4},{'name':'House Salad','calories': 100,'cost': 8.5},{'name':'Grilled Shrimp','calories': 400,'cost': 15},{'name':'Beef Brisket','cost': 12},{'name':'Soda','cost': 1},{'name':'Cake','calories': 300,'cost': 3},]

def menu_recommendation(menu,min_cal,max_cal,budget):
    menu = [item for item in menu if item['calories'] <= max_cal and item['cost'] <= budget]
    if len(menu) == 0: return []
    return min((
        [item] + menu_recommendation(menu,min_cal - item['calories'],max_cal - item['calories'],budget - item['cost'])
        for item in menu
    ),key= 
        lambda recommendations: [budget - sum(item['cost'] for item in recommendations) and min_cal <= sum(item['calories'] for item in recommendations) <= max_cal,-sum(item['calories'] for item in recommendations)]
    )

recommendation = menu_recommendation(menu,1000,1200,15)
total_cost = sum(item['cost'] for item in recommendation)
total_cals = sum(item['calories'] for item in recommendation)
print(f'recommendation: {recommendation}')
print(f'total cost: {total_cost}')
print(f'total calories: {total_cals}')

例如,以下代码返回总热量为700(低于最小值1000)的解决方案。 推荐= menu_recommendation(菜单,1000,1200,15)

解决方法

我们可以递归地进行一些工作。

def smallest_combo(lst,m,n,z):
    # filter list to remove elements we can't use next without breaking the rules
    lst = [dct for dct in lst if m <= dct['x'] <= n and dct['y'] <= z]
    # recursive base case
    if len(lst) == 0:
        return []
    # go through our list of eligibles
    # simulate 'what would the best possibility be if we picked that one to go with next'
    # then of those results select the one with the sum('y') closest to z
    #   (breaking ties with the largest sum('x'))
    return min((
        [dct] + smallest_combo(lst,m - dct['x'],n - dct['x'],z - dct['y'])
        for dct in lst
    ),key= 
        lambda com: [z - sum(d['y'] for d in com),-sum(d['x'] for d in com)]
    )

inp = [{'name': 'item1','x': 600,'y': 5},{'name': 'item2','x': 200,'y': 8},{'name': 'item3','x': 500,'y': 12.5},{'name': 'item4','x': 0,'y': 1.5},{'name': 'item5','x': 100,'y': 1}]
print(smallest_combo(inp,500,1500,25))
# [{'name': 'item3','y': 12.5}]

有多种方法可以加快此过程。首先是建立递归缓存,其次是采用动态编程方法(即从底部开始而不是从顶部开始)。

,

这是一个动态编程解决方案,它建立一个数据结构,显示我们可以使用的所有(calorie,cost)选项以及每个选项。我们会寻找符合标准的最佳人选,然后找到建议。

def menu_recommendation(menu,min_cal,max_cal,budget):
    # This finds the best possible solution in pseudo-polynomial time.
    recommendation_tree = {(0,0.0): None}
    for item in menu:
        # This tree will wind up being the old plus new entries from adding this item.
        new_recommendation_tree = {}
        for key in recommendation_tree.keys():
            calories,cost = key
            new_recommendation_tree[key] = recommendation_tree[key]
            new_key = (calories + item['calories'],cost + item['cost'])
            if new_key not in recommendation_tree and new_key[0] <= max_cal:
                # This is a new calorie/cost combination to look at.
                new_recommendation_tree[new_key] = item
        # And now save the work.
        recommendation_tree = new_recommendation_tree

    # Now we look for the best combination.
    best = None
    for key in recommendation_tree:
        calories,cost = key
        # By construction,we know that calories <= max_cal
        if min_cal <= calories:
            if best is None or abs(budget - cost) < abs(budget - best[1]):
                # We improved!
                best = key

    if best is None:
        return None
    else:
        # We need to follow the tree back to the root to find the recommendation
        calories,cost = best
        item = recommendation_tree[best]
        answer = []
        while item is not None:
            # This item is part of the menu.
            answer.append(item)
            # And now find where we were before adding this item.
            calories = calories - item['calories']
            cost = cost - item['cost']
            best = (calories,cost)
            item = recommendation_tree[best]
        return answer
,

我想到了这一点,它基本上是背包,但是如果不适合推荐,它将从菜单中递归删除菜品

menu = [
    {'name':'Cheese Pizza Slice','calories': 700,'cost': 4},{'name':'House Salad','calories': 100,'cost': 8.5},{'name':'Grilled Shrimp','calories': 400,'cost': 15},{'name':'Beef Brisket','cost': 12},{'name':'Soda','cost': 1},{'name':'Cake','calories': 300,'cost': 3},]



def get_price(recommendation):
    return sum(dish["cost"] for dish in recommendation)

def get_calories(recommendation):
    return sum(dish["calories"] for dish in recommendation)

def menu_recommendation(menu,budget):
    sorted_menu = sorted(menu,key=lambda dish: dish["cost"],reverse=True)
    recommendation = []
    for dish in sorted_menu:
      if dish["cost"] + get_price(recommendation) <= budget:
        recommendation.append(dish)
    if recommendation:
      if get_calories(recommendation) < min_cal:
        sorted_menu.remove(min(recommendation,key=lambda dish: dish["calories"]/dish["cost"]))
        return menu_recommendation(sorted_menu,budget)
      if get_calories(recommendation) > max_cal:
        sorted_menu.remove(max(recommendation,budget)
    return recommendation




recommendation = menu_recommendation(menu,800,15)
total_cost = sum(item['cost'] for item in recommendation)
total_cals = sum(item['calories'] for item in recommendation)
print(f'recommendation: {recommendation}')
print(f'total cost: {total_cost}')
 

它根据卡路里/成本比率删除元素,因为这是背负背包的成本。

如有任何疑问,请告诉我。

,

我相信我已经解决了提出超出min_cal / max_cal范围的建议的问题,但是我仍然觉得可能存在一种更接近预算的解决方案。

这是我更新的代码:

menu = [
    {'name':'Cheese Pizza Slice',]

def menu_recommendation(menu,budget):
    menu = [item for item in menu if item['calories'] <= max_cal and item['cost'] <= budget]
    if len(menu) == 0: return []
    return min(([item] + menu_recommendation(menu,min_cal - item['calories'],max_cal - item['calories'],budget - item['cost']) 
        for item in menu
),key= 
    lambda recommendations: [budget - sum(item['cost'] for item in recommendations) 
                             and min_cal - sum(item['calories'] for item in recommendations) >= 0
                             and max_cal - sum(item['calories'] for item in recommendations) >= 0,-sum(item['calories'] for item in recommendations)]
)

recommendation = menu_recommendation(menu,1000,1200,15)
total_cost = sum(item['cost'] for item in recommendation)
total_cals = sum(item['calories'] for item in recommendation)
print(f'recommendation: {recommendation}')
print(f'total cost: {total_cost}')
print(f'total calories: {total_cals}')

如果有人有任何改进,我希望听到他们的声音!

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...