0

I have the following df of fruits:

    fruit            cost
0   Banana             10 
1   Apple               5        
2   Orange              4
3   Grape               2
4   Kiwi                3

I want to create a list of 3 fruits (obligatory - no more, no less) with a budget of $15. The df is already ordered so I want to start choosing fruits from the first row and iterate through the df.

The list wound end up being (accounting for budget and fruit limit):

[Banana, Grape, Kiwi]

This is my code:

def fruit_list(df, budget = 15)
    list = []
    budget = budget
    iter = df.iterrows()
    for (i, row1), (j, row2) in zip(iter, iter):
        if (len(list) < 3 and budget > row1['cost'] and 
            budget - row1['cost'] > row2['cost']):
            list.append(row1['fruit'])
            budget -= row1['cost']
    return fruit_list

My code is leaving a 2-fruit list, instead of 3. Basically I would like my code to compare a fruit's price with ALL of the remaining fruit's prices and not just the next one. How should I tackle this?

**(EXTRA) This is what the iterating process should look like:

Budget = $15

Iteration 1 --> Banana

  • Add Banana to list
  • Budget = $15 - $10 = $5*

Iteration 2 --> Apple

  • SKIP Apple because:
  • Budget = $5 - $5 = $0
  • No more budget to buy more fruits, and I need 3 fruits

Iteration 3 --> Orange

  • SKIP Orange because:
  • Budget = $5 - $4 = $1
  • Not enough budget to buy any of the remaining fruits, and I need 3 fruits

Iteration 4 --> Grape

  • Add Grape to list
  • Budget = $5 - $2 = $3
  • Enough budget to buy the remaining fruit, Kiwi

Iteration 5 --> Kiwi

  • Add Kiwi to list
  • Budget = $3 - $3 = $0
grungrun
  • 13
  • 5
  • https://stackoverflow.com/a/58119966/6361531 – Scott Boston Jul 30 '22 at 01:51
  • Do you want an exact budget match? If not do you need to maximize/minimize the budget? In my answer below I assumed an exact match (or the first match even if not not optimal if you were to use `<=15` in place of `=15`) – mozway Jul 30 '22 at 02:08

1 Answers1

0

As you have a fixed number of items and want the first match, this is easily done in pure python by looping through the combinations:

from itertools import combinations

s = df.set_index('fruit')['cost']

out = next((c for c in combinations(df['fruit'], 3)
            if s.loc[list(c)].sum()==15), None)

Output: ('Banana', 'Grape', 'Kiwi')

Since we are using a generator here, the computation stops as soon as we found a match without needlessly computing the rest of the combinations.

mozway
  • 194,879
  • 13
  • 39
  • 75