I was working on a problem that has to deal with a special case of the Knapsack/Subset-Sum Problem. The problem is as follows:
You have a set of bundle sizes in decreasing sizes that are random like: {47, 35, 22, ...}
. You have value that is the quantity of widgets like: #widgets = 33.
Find the least number of bundles that can make up the number of widgets for the bundle. If there is no way to return set that equals quantities then return null.
- Example 1:
- Bundle Sizes: 46, 25, 12, 4, 3
- quantity: 30
- Returned Value: {46:0, 25:0, 12:2, 4:0, 3:2} (bundle size:# of bundles)
- Example 2:
- Bundle Sizes: 46, 25, 12, 4, 3
- quantity: 17
- Returned Value: {46:0, 25:0, 12:0, 4:2, 3:3}
- Example 3:
- Bundle Sizes: 46, 25, 12, 4, 3
- quantity: 47
- Returned Value: {46:0, 25:1, 12:1, 4:1, 3:2}
- Example 4:
- Bundle Sizes: 46, 25, 12, 4, 3
- quantity: 5
- Returned Value: null
How would go about this problem?
I have written a program in C# that does close enough job but resets an index in a for loop to dump bundle sizes that will not work with the rest of the set. Will post source if requested for how far it goes.
Requested code:
public List<int> BreakDown(List<int> bunSize, int buySize)
{
List<int> tempBunSize = bunSize.ToList();
tempBunSize.RemoveAll(e => e > buySize);
List<int> ammountNeeded = new List<int>();
int result = buySize;
for (int index = 0; index < tempBunSize.Count; index++)
{
int size = tempBunSize[index];
int tempResult = 0;
double calcResult = 0;
int addAmmount = 0;
if (index == tempBunSize.Count - 2)
{
tempResult = result % size;
if ((tempBunSize.Count > 2 || result % tempBunSize[tempBunSize.Count - 1] == 0))
{
if (result % size != 0)
{
ammountNeeded.Add(0);
tempResult = result % tempBunSize[tempBunSize.Count - 1];
if (tempResult != 0)
{
tempResult = result;
int sizeInc = 0;
while (tempResult != 0)
{
tempResult = tempResult - size;
sizeInc++;
if (tempResult < 0)
{
int decreaseOne = ammountNeeded.First();
ammountNeeded[0] = --decreaseOne;
result = result + tempBunSize.First();
if (ammountNeeded[0] <= 0)
{
tempBunSize.RemoveAt(0);
index = 0;
ammountNeeded = new List<int>();
}
ammountNeeded.Remove(0);
--index;
break;
}
if (tempResult % tempBunSize[tempBunSize.Count - 1] == 0)
{
ammountNeeded.Remove(0);
ammountNeeded.Add(sizeInc);
ammountNeeded.Add(tempResult / tempBunSize[tempBunSize.Count - 1]);
break;
}
}
if (tempResult < 0) continue;
break;
}
else
{
calcResult = result / tempBunSize[tempBunSize.Count - 1];
addAmmount = (int)Math.Floor(calcResult);
ammountNeeded.Add(addAmmount);
break;
}
}
else if (result % size == 0)
{
tempResult = result % size;
if (tempResult != 0 && result % tempBunSize[tempBunSize.Count - 1] != 0)
{
int decreaseOne = ammountNeeded.First();
ammountNeeded.Insert(0, --decreaseOne);
result = result + tempBunSize.First();
continue;
}
else
{
calcResult = result / size;
addAmmount = (int)Math.Floor(calcResult);
ammountNeeded.Add(addAmmount);
if (result % size == 0)
{
ammountNeeded.Add(0);
break;
}
calcResult = result / tempBunSize[tempBunSize.Count - 1];
addAmmount = (int)Math.Floor(calcResult);
ammountNeeded.Add(addAmmount);
break;
}
}
}
else if (tempResult % tempBunSize[tempBunSize.Count - 1] != 0)
{
tempResult = result;
int sizeInc = 0;
while (tempResult != 0)
{
tempResult = tempResult - size;
sizeInc++;
if (tempResult % tempBunSize[tempBunSize.Count - 1] == 0)
{
ammountNeeded.Add(sizeInc);
ammountNeeded.Add(tempResult / tempBunSize[tempBunSize.Count - 1]);
break;
}
}
break;
}
else if (result == 0)
{
while (ammountNeeded.Count < bunSize.Count)
{
ammountNeeded.Add(0);
}
break;
}
else
{
calcResult = result / size;
ammountNeeded.Add((int)Math.Floor(calcResult));
calcResult = tempResult / tempBunSize[tempBunSize.Count - 1];
ammountNeeded.Add((int)Math.Floor(calcResult));
break;
}
}
ammountNeeded.Add((int)Math.Floor((decimal)result / size));
result = result % size;
if (result == 0) continue;
}
if (ammountNeeded.Count < bunSize.Count)
{
ammountNeeded.Reverse(0, ammountNeeded.Count);
while (ammountNeeded.Count < bunSize.Count)
{
ammountNeeded.Add(0);
}
ammountNeeded.Reverse(0, ammountNeeded.Count);
}
if (ammountNeeded.FindLast(e => e < 0) < 0 || ammountNeeded.Sum() == 0)
return null;
return ammountNeeded;
}
}