I was practicing with a GeeksForGeeks problem Fractional Knapsack:
Given weights and values of N items, we need to put these items in a knapsack of capacity W to get the maximum total value in the knapsack.
Note: Unlike 0/1 knapsack, you are allowed to break the item.
Example 1:
Input:
N = 3, W = 50
values[] = {60,100,120}
weight[] = {10,20,30}Output:
240.00
Explanation
Total maximum value of item we can have is 240.00 from the given capacity of sack.
When I submit my code, the online judge tells me my code returns a wrong answer, however when I run the same test case on custom input, I get the expected answer by the judge.
I searched as to why this happened, and the potential reasons I came across were because of Global/Static variables, however I am not using any global/static variables.
My Approach for the problem was :
The code I am using :
### Item class for reference
class Item:
def __init__(self,val,w):
self.value = val
self.weight = w
class Solution:
def fractionalknapsack(self, W,arr,n):
hashmap = {(item.value / item.weight) : item for i,item in enumerate(arr) }
keys = list(hashmap.keys())
keys.sort()
sorted_hashmap = {}
keys.reverse()
for ele in keys :
sorted_hashmap[ele] = hashmap[ele]
final_ans = 0
available_weight = W
for ratio,item in sorted_hashmap.items() :
if available_weight > 0 :
if item.weight <= available_weight :
final_ans += item.value
available_weight -= item.weight
else :
final_ans += available_weight * ratio
break
else :
break
return final_ans
The input for which the test succeeds, but submission fails:
Input :
84 87
78 16 94 36 87 43 50 22 63 28 91 10 64 27 41 27 73 37 12 19 68 30 83 31 63 24 68 36 30 3 23 9 70 18 94 7 12 43 30 24 22 20 85 38 99 25 16 21 14 27 92 31 57 24 63 21 97 32 6 26 85 28 37 6 47 30 14 8 25 46 83 46 15 18 35 15 44 1 88 9 77 29 89 35 4 2 55 50 33 11 77 19 40 13 27 37 95 40 96 21 35 29 68 2 98 3 18 43 53 7 2 31 87 42 66 40 45 20 41 30 32 18 98 22 82 26 10 28 68 7 98 4 87 16 7 34 20 25 29 22 33 30 4 20 71 19 9 16 41 50 97 24 19 46 47 2 22 6 80 39 65 29 42 1 94 1 35 15
Output :
Online Judges Expected Output : 1078.00
My Submission Output : 235.58
My custom input output : 1078.00
This is indeed very confusing! I looked at the Python version that GeeksForGeeks is running your code on, and at the time of writing these versions are different depending on whether you test or submit!
This explains why you get different results when testing versus submitting. Since Python 3.6 dictionaries are iterated in insertion order, but in older versions the iteration order is undefined -- there is no guarantee whatsoever that the order in which you inserted the items will also be the order in which the items are iterated.
Taking a step back, you should not need a dictionary here. In fact, it will be problematic when two items happen to have the same ratio, because then you will lose out on one.
Solve this by just sorting the input items by the ratio. Here is your code with the hasmap removed, and the sort
called on the input list instead:
class Solution:
def fractionalknapsack(self, W, arr, n):
arr.sort(key=lambda item: item.value / item.weight, reverse=True)
final_ans = 0
available_weight = W
for item in arr:
if available_weight > 0:
if item.weight <= available_weight:
final_ans += item.value
available_weight -= item.weight
else :
final_ans += available_weight * item.value / item.weight
break
else:
break
return final_ans