0

I am coding this program to solve the following equation: ax+by+cz+....+nk <= d a, b, c, ..., n and d will be input by user.

Imaging that a, b, c, ..., n are the price list and x y z... k are the quantity. Giving you a money amount of d, you need to optimize the good quantity that you can buy until you cannot buy anything else with your leftover.

My program is running fine with small amount of good (5). If I input following values: - Number of good: 6 - Price list: - Item 1: 600 - Item 2: 900 - Item 3: 1200 - Item 4: 1600 - Item 5: 1800 - Item 6: 2400 - Total: 6000

, it will cause "AWT-EventQueue-0" java.lang.StackOverflowError.

Can you please help check and suggest where can I improve it?

    btnNhpLngHng.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            isValid = true;
            isValid = validateField();
            if (!isValid)
                JOptionPane.showMessageDialog(null, "Please input valid data");
            else
                goodQuantity = Integer.parseInt(goodQuantityTF.getText());
                headerList = new Vector<String>(goodQuantity);
                priceList = new Vector<Long>(goodQuantity);
                quantityList = new Vector<Long>(goodQuantity);
                isChecked = new Vector<Boolean>(goodQuantity);
                for (int i = 1; i <= goodQuantity; i++) {
                    headerList.add("Mặt hàng " + i);
                    isChecked.add(false);
                    quantityList.add((long) 0);
                }

                for (int i = 0; i < goodQuantity; i++) {
                    vitrihang = i;
                    gianhap = Long.parseLong(JOptionPane.showInputDialog("Please input the price for good no." + (vitrihang+1)));
                    priceList.add(gianhap);
                }
                expectedSum = Long.parseLong(JOptionPane.showInputDialog("Please input expected total amount: "));

        }
    });

    btnKimTra.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            for (int x1 = goodQuantity - 1; x1 > -1; x1--) {
                inProcess = x1;
                isDone = false;
                timNghiem(x1);

            }
        }
    });
}

public boolean validateField() {
    if (goodQuantityTF.getText() == null)
        return false;
    else
        try {
            Double n = Double.parseDouble(goodQuantityTF.getText());
        }
        catch(Exception e) {
            return false;
        }

    return true;
}

public void timNghiem(int a) {
    //System.out.println(a);
    if ((a+1) == goodQuantity) {
        kiemNghiem();
        isChecked.set(a, true);
        if ((inProcess + 1) == goodQuantity) {
            return;

        } else {
            timNghiem(a-1);
            if (isChecked.get(inProcess)) {
                isDone = true;
                return;
            }
        }
    } else {
        if (!isChecked.get(a)) {
            if (quantityList.get(a) <= (expectedSum/priceList.get(a))) {
                tangNghiem(a);
                kiemNghiem();
                resetIsChecked(a);
                timNghiem(a+1);
                if (isChecked.get(inProcess)) {
                    isDone = true;
                    return;
                }
            } else {
                isChecked.set(a, true);
                if (isChecked.get(inProcess)) {
                    isDone = true;
                    return;
                } else {
                    for (int x2 = inProcess; x2 < goodQuantity; x2++) {
                        if (!isChecked.get(x2)) {
                            if (isChecked.get(x2+1)) {
                                timNghiem(x2);
                            }
                        }
                    }
                }
            }
        }
    }

}

public void kiemNghiem() {
    quantityList.set(goodQuantity-1, (long) 0);
    do {
        currentSum = 0;
        for (int n = 0; n < goodQuantity; n++) {
            currentSum = currentSum + priceList.get(n)*quantityList.get(n);
            //System.out.println(priceList.get(n)*quantityList.get(n));
        }

        if (currentSum <= expectedSum) {
            leftOver = expectedSum - currentSum;
            isResult = true;

            for (int n = 0; n< goodQuantity; n++) {
                if (leftOver > priceList.get(n)) {
                    isResult = false;
                }
            }

            if (isResult) {
                result = "";
                for (int n = 0; n < goodQuantity; n++){
                    result = result + quantityList.get(n) + " ";
                }
                System.out.println(result);
            }
        }
        quantityList.set(goodQuantity-1, quantityList.get(goodQuantity-1)+1);
    }
    while (currentSum <= expectedSum);

}

public void tangNghiem(int a) {
    quantityList.set(a, quantityList.get(a)+1);
    for (int k = a + 1; k < goodQuantity; k++) {
        quantityList.set(k, (long) 0);
    }
}

public void resetIsChecked(int a) {
    for (int k = a + 1; k < goodQuantity; k++) {
        isChecked.set(k, false);
    }
}

}

  • 1
    The exception will tell you where your recursion is going off the rails. Your options include creating and running a non-recursive solution. – Hovercraft Full Of Eels Nov 24 '17 at 15:39
  • Yes but it tells me the whole list of event queue, containing all active event. The problem is that this does not happen if the number of good is lower. Besides, how can I solve this unknown number of good without recursion, can you please help me a little bit more detail? – Khoa Đặng Quang Nov 24 '17 at 15:41
  • ? Of course it doesn't happen when the number is lower -- the recursion is less in that situation. Again, your problem is nothing more than too much recursion causing you to run out of stack memory, and this only happens when the recursive load is high (the number of goods is higher). – Hovercraft Full Of Eels Nov 24 '17 at 15:42
  • Side note: the question has nothing to do with GUI programming or Swing. In the future you'll want to extract out the key problem-related portions of the code into its own stand-alone [mcve] program. If nothing else, this will force you to refactor out the non-GUI code from the GUI code, a useful processes in its own right. – Hovercraft Full Of Eels Nov 24 '17 at 15:45
  • @HovercraftFullOfEels Thank you very much in deed, I am going through the debugging recursive topic overthere. Btw, I have editted the code block so it focuses more on the problem. – Khoa Đặng Quang Nov 24 '17 at 15:52
  • No, you've simply extracted a snippet and have not posted a valid [mcve]. Please read the MCVE link to see what is required: a stand alone small program, one that has the code needed to compile and run, and that reproduces the problem. This can easily be achieved by extracting the logical non-GUI **model** code from your program above (something that you should be doing regardless, for good programming practices). Extract it to a single class that might use other non-gui helper classes, that accepts necessary data and does needed calculations. – Hovercraft Full Of Eels Nov 24 '17 at 15:55

0 Answers0