为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

皈依舞 2023-09-26 17:16:49
我在将返回的解决方案正确装箱为 min_cals <= sum(calories) <= max_cals 时遇到一些困难。有一些组合可以产生 sum(cals) < 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', 'calories': 400, 'cost': 12},    {'name':'Soda', 'calories': 100, '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)
查看完整描述

4 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

我想出了这个,它基本上是一个背包,但如果不适合推荐,它会从菜单中递归删除菜肴:


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', 'calories': 400, 'cost': 12},

    {'name':'Soda', 'calories': 100, '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, min_cal, max_cal, 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, min_cal, max_cal, budget)

      if get_calories(recommendation) > max_cal:

        sorted_menu.remove(max(recommendation, key=lambda dish: dish["calories"]/dish["cost"]))

        return menu_recommendation(sorted_menu, min_cal, max_cal, budget)

    return recommendation





recommendation = menu_recommendation(menu, 500, 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}')

 

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


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


查看完整回答
反对 回复 2023-09-26
?
ibeautiful

TA贡献1993条经验 获得超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


查看完整回答
反对 回复 2023-09-26
?
GCT1015

TA贡献1827条经验 获得超4个赞

也许我们可以做一些递归的事情。


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', 'x': 500, 'y': 12.5}, {'name': 'item3', 'x': 500, 'y': 12.5}]

有多种方法可以加快这一速度。首先通过制作递归缓存,然后采用动态编程方法(即从底部开始而不是从顶部开始)。


查看完整回答
反对 回复 2023-09-26
?
烙印99

TA贡献1829条经验 获得超13个赞

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


这是我更新的代码:


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', 'calories': 400, 'cost': 12},

    {'name':'Soda', 'calories': 100, '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) >= 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}')

如果有人有任何改进,我很乐意听到他们的声音!


查看完整回答
反对 回复 2023-09-26
  • 4 回答
  • 0 关注
  • 98 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信