Python Dictionary Practice Problems Q12 - Laptop Purchase

URL to problem: Learn data science with Python and R projects

I was working through the practice problems for Python Dictionaries.

For the last problem, you need to make a dictionary called price_to_name where the key a price, and the value is the list of all laptop names with that price (there can be more than one laptop with a given price).

After that,

  1. Using the price_to_name dictionary that you just created, figure out whether there exist two laptops whose total cost is exactly $5,000.
  2. Assign the first laptop in the solution to a variable named laptop1 and the second to a variable named laptop2. If there are several solutions, anyone will be marked as correct.

Here’s what I tried to do:

My Code:

laptop1 = '' 
laptop2 = ''

for price1, list1 in price_to_name.items():
    for price2, list2 in price_to_name.items():
        total = price1 + price2
        laptop_a = list1[0]
        laptop_b = list2[0]
        if total == 5000 and (laptop_a != laptop_b):
            laptop1 = laptop_a
            laptop2 = laptop_b
    break

What I expected to happen:

  • That laptop1 and laptop2 would get the right values.

What actually happened:

  • laptop1 and laptop2 did not change.

I can’t figure out why. Would greatly appreciate any help on this!

Thanks,
Barry

Please make sure to include a link to the practice problem as well in your post. Otherwise, there’s not enough context for others to be able to help out.

1 Like

While I like your approach to solving this problem, I see a couple of issues we should take a look at. The first issue is with the use of break. And while removing it does not provide a solution, I just wanted to point out how it is affecting your algorithm. Check out the code chunks below to see the difference.

laptop1 = '' 
laptop2 = ''
counter = 0
for price1, list1 in price_to_name.items():
    for price2, list2 in price_to_name.items():
        total = price1 + price2
        laptop_a = list1[0]
        laptop_b = list2[0]
        counter += 1
        if total == 5000 and (laptop_a != laptop_b):
            laptop1 = laptop_a
            laptop2 = laptop_b
    break            
print(counter)

Output: 400

And now without break:

laptop1 = '' 
laptop2 = ''
counter = 0
for price1, list1 in price_to_name.items():
    for price2, list2 in price_to_name.items():
        total = price1 + price2
        laptop_a = list1[0]
        laptop_b = list2[0]
        counter += 1
        if total == 5000 and (laptop_a != laptop_b):
            laptop1 = laptop_a
            laptop2 = laptop_b
                
print(counter)

Output: 160000

So what does this all mean? Well, in the first code block, the nested loops ran for a total of 400 iterations, which is the same as len(price_to_name). This tells us that the outer loop only ran for the first item in price_to_name (ie price1=1340 and list1='MacBook Pro') and never moved on to the next items in price_to_name. In other words, as it stand right now, this nested loop will only try combinations of prices for the first element against all other elements in the dictionary. We don’t want this.

Compare this to the second code block (with break removed) we see that it ran for a total of 160000 iterations, which is equivalent to 400*400. In other words, it is comparing every price against every other price in price_to_name…which is what we want! Alright, so we should start by removing break.

Ok, so far so good? We know we want to remove break so that we are trying all possible combinations. But it still doesn’t produce a solution…so…why not?!

Well, this is where a more critical flaw comes into play: what happens if there aren’t two laptops with different prices that sum to $5000 BUT there are two different laptops with the same price that sum to $5000? How will our code deal with that situation? Let’s walk through it.

If two different laptops have prices that sum to $5000, that means that their price is $2500 each, which means they have the same key in price_to_name. Therefore, price1 = price2 = 2500 and as a consequence, list1 = list2. This also implies that laptop_a must be the same as laptop_b since they are both being assigned as the first item in list1 and list2 (which are equivalent lists). In other words, list1[0] == list2[0] is True. Under these conditions, the if statement will never be executed since laptop_a != laptop_b will always evaluate to False.

So to recap, if there aren’t two laptops with different prices but there are two laptops with the same price, the variables laptop1 and laptop2 will never be assigned a value; they will remain empty strings.

Now the million dollar question is: how do we fix it? Well, the simplest way to modify the code we have already would be to add an elif clause to deal with the situation I just described above.

My advice: construct an elif clause that deals with the situation where the total is $5000 and list1 is the same as list2 and also make sure that the list has more than one element in it. That last part of the clause is important since it essentially checks to make sure there are two different laptops in the list. If those conditions are met, assign values to laptop_a and laptop_b by selecting different elements in the list by using different indices.

I don’t feel my answer would be truly complete unless I were to mention that there is a much simpler way to solve this problem without using nested loops. As you saw above with the counter variable, nested loops can be computationally expensive and therefore we should try to avoid them if possible. That said, I really want you to solve it using your own approach first!

Let me know how you make out and if there’s anything else I can help you understand.

1 Like

My bad, thanks! Have done so.

Thanks so much again for the extensive reply. I’ll need to take some time to mull over what you mentioned!

Once I work out something out I’ll let you know! I was also pretty reticent about using a nested loop for the reason you mention (thus the break, but I wasn’t thinking clearly enough about the consequences), so I’m pretty keen to hear what you see as a simpler way to solve this problem.

1 Like

No worries, take your time! While we agree that using a nested loop isn’t the most elegant solution, I believe making it work is still a worthwhile learning experience before exploring a better solution.