Search This Blog

Monday, May 3, 2010

Subset sum problem

Programmer Question


I'm having a problem with counting which is continuation of this question. I am not really a math person so it's really hard for me to figure out this subset sum problem which was suggested as resolution.



I'm having 4 ArrayList in which I hold data: alId, alTransaction, alNumber, alPrice




Type | Transaction | Number | Price

8 | Buy | 95.00000000 | 305.00000000

8 | Buy | 126.00000000 | 305.00000000

8 | Buy | 93.00000000 | 306.00000000

8 | Transfer out | 221.00000000 | 305.00000000

8 | Transfer in | 221.00000000 | 305.00000000

8 | Sell | 93.00000000 | 360.00000000

8 | Sell | 95.00000000 | 360.00000000

8 | Sell | 126.00000000 | 360.00000000

8 | Buy | 276.00000000 | 380.00000000




In the end I'm trying to get what's left for customer and what's left I put into 3 array lists:

- alNewHowMuch (corresponds to alNumber),

- alNewPrice (corresponds to alPrice),

- alNewInID (corrseponds to alID)



        ArrayList alNewHowMuch = new ArrayList();
ArrayList alNewPrice = new ArrayList();
ArrayList alNewInID = new ArrayList();
for (int i = 0; i < alTransaction.Count; i++) {
string transaction = (string) alTransaction[i];
string id = (string) alID[i];
decimal price = (decimal) alPrice[i];
decimal number = (decimal) alNumber[i];
switch (transaction) {
case "Transfer out":
case "Sell":
int index = alNewHowMuch.IndexOf(number);
if (index != -1) {
alNewHowMuch.RemoveAt(index);
alNewPrice.RemoveAt(index);
alNewInID.RemoveAt(index);
} else {
ArrayList alTemp = new ArrayList();
decimal sum = 0;
for (int j = 0; j < alNewHowMuch.Count; j ++) {
string tempid = (string) alNewInID[j];
decimal tempPrice = (decimal) alNewPrice[j];
decimal tempNumbers = (decimal) alNewHowMuch[j];
if (id == tempid && tempPrice == price) {
alTemp.Add(j);
sum = sum + tempNumbers;
}
}
if (sum == number) {
for (int j = alTemp.Count - 1; j >= 0; j --) {
int tempIndex = (int) alTemp[j];
alNewHowMuch.RemoveAt(tempIndex);
alNewPrice.RemoveAt(tempIndex);
alNewInID.RemoveAt(tempIndex);
}
}
}
break;
case "Transfer In":
case "Buy":
alNewHowMuch.Add(number);
alNewPrice.Add(price);
alNewInID.Add(id);
break;
}
}


Basically I'm adding and removing things from Array depending on Transaction Type, Transaction ID and Numbers. I'm adding numbers to ArrayList like 156, 340 (when it is TransferIn or Buy) etc and then i remove them doing it like 156, 340 (when it's TransferOut, Sell). My solution works for that without a problem. The problem I have is that for some old data employees were entering sum's like 1500 instead of 500+400+100+500. How would I change it so that when there's Sell/TransferOut or Buy/Transfer In and there's no match inside ArrayList it should try to add multiple items from thatArrayList and find elements that combine into aggregate.



Inside my code I tried to resolve that problem with simple summing everything when there's no match (index == 1)



                    int index = alNewHowMuch.IndexOf(number);
if (index != -1) {
alNewHowMuch.RemoveAt(index);
alNewPrice.RemoveAt(index);
alNewInID.RemoveAt(index);
} else {
ArrayList alTemp = new ArrayList();
decimal sum = 0;
for (int j = 0; j < alNewHowMuch.Count; j ++) {
string tempid = (string) alNewInID[j];
decimal tempPrice = (decimal) alNewPrice[j];
decimal tempNumbers = (decimal) alNewHowMuch[j];
if (id == tempid && tempPrice == price) {
alTemp.Add(j);
sum = sum + tempNumbers;
}
}
if (sum == number) {
for (int j = alTemp.Count - 1; j >= 0; j --) {
int tempIndex = (int) alTemp[j];
alNewHowMuch.RemoveAt(tempIndex);
alNewPrice.RemoveAt(tempIndex);
alNewInID.RemoveAt(tempIndex);
}
}
}


But it only works if certain conditions are met, and fails for the rest.



Edit: Since some of you were so astonished (and blinded) by my polish variable names i translated all of them to english for simplicity and visiblity. Hopefully this will help me to get some help :-)





Find the answer here

No comments:

Post a Comment

Related Posts with Thumbnails