0

Okay. So I'm trying to write an applicaton that solves problems in the correct order of operations (i.e. PEMDAS, but without the PE lol). I'm probably doing this wrong, but whatever. What I need help on is that as a iterate through each element in the array, if it is an operator, I remove two elements(the numbers surrounding the operator because I replace the operator the correct computation, so an array with three elements, 5+5, will become an array with one element, 10) which would be fine, but the for-statement condition doesn't update, so, in other words, when i update the array, the array.length gets shorter, but the for-statement doesn't recognize that and continues on pass the bounds of the array, this causes outofbounds errors. Best way to explain is by my code, so here it is:

for (i = 0; i < splitEquation.length; i++){
        if (splitEquation[i].equals("*")){
            splitEquation[i] = Double.toString(Double.parseDouble(splitEquation[i - 1]) * Double.parseDouble(splitEquation[i + 1]));
            splitEquation = removeIndex(splitEquation, i - 1);
            splitEquation = removeIndex(splitEquation, i + 1);
            solution += Double.parseDouble(splitEquation[i - 1]);

        }
}

And removeIndex():

private String[] removeIndex(String [] s, int index){
    String [] n = new String[s.length - 1];

    System.arraycopy(s, 0, n, 0, index - 1);
    System.arraycopy(s, index, n, index - 1, s.length - index);
    return n;
}

Thanks in advance, -Eric

P.S. Let me know if you need any clarification of what my code does :)

Eric
  • 51
  • 1
  • 6

3 Answers3

0

Using an ArrayList Would make your life a whole lot easier:

ArrayList<String> splitEquation = 
    new ArrayList<String>(Arrays.toList("5","*","5"));

for (i = 0; i < splitEquation.size(); i++){
    if (splitEquation.get(i).equals("*")) {
        splitEquation.set(i, 
            (Double.toString(Double.parseDouble(splitEquation.get(i - 1)) * 
                Double.parseDouble(splitEquation.get(i + 1))));
        splitEquation.remove(i - 1); // shortens array by 1
        splitEquation.remove(i); // this used to be (i + 1)
        i--; // move back one (your computed value)
        solution += Double.parseDouble(splitEquation.get(i));

    }
}

That being said ... do you really need to modify your array in place?

EDIT: The question is now more clear, the array was being modified because it needs to be evaluated as a series of expressions. He also wants to add addition and subtraction:

Recursive functions are your friend :)

public static double result(ArrayList<String> mySequence, double total, int index)
{
    if (index == 0)
        total = Double.parseDouble(mySequence.get(index));

    if (index == (mySequence.size() - 1))
        return total;
    else if (mySequence.get(index).equals("*"))
        total *= Double.parseDouble(mySequence.get(index + 1));
    else if (mySequence.get(index).equals("/"))
        total /= Double.parseDouble(mySequence.get(index + 1));
    else if (mySequence.get(index).equals("+"))
    {
        index++;
        double start = Double.parseDouble(mySequence.get(index));
        total += result(mySequence, start, index);
        return total;
    }
    else if (mySequence.get(index).equals("-"))
    {
        index++;
        double start = Double.parseDouble(mySequence.get(index));
        total -= result(mySequence, start, index);
        return total;
    }

    index++;
    return result(mySequence, total, index);

}

public static void main(String args[])
{
    ArrayList<String> splitEquation = 
        new ArrayList<String>(
            Arrays.asList("5","*","5","/","5","*","4","-","3","*","8"));

    double myResult = result(splitEquation, 0, 0); 
    System.out.println("Answer is: " + myResult);
}

Output:

Answer is: -4.0

Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • But won't that still go out of bounds in the end? If I remove it the for statement will still continue. Well modifying it is the only method I can think of :/ thank you though! – Eric Apr 03 '11 at 16:32
  • It's not going to go out of bounds because of the `i--;` - it's setting the iterator to a valid element. It then gets incremented by the loop and compared to `i < splitEquation.size()` which then causes the loop to exit (if you're at the end of the arraylist) – Brian Roach Apr 03 '11 at 16:37
  • What's the purpose of modifying the array in place? You want to end up with an array of the computed values? Why not just use a second array for the results? – Brian Roach Apr 03 '11 at 16:43
  • Hmm, so you mean, for example after i get 5 + 5, i put that into another array and just continue to iterate? – Eric Apr 03 '11 at 16:45
  • Correct. You would just need to put the result in a second ArrayList and do `i++` to jump forward one instead of removing the elements and doing `i--` – Brian Roach Apr 03 '11 at 16:48
  • See edited answer. You move your iterator forward one so that it is pointing at your second string (the second `5`) – Brian Roach Apr 03 '11 at 16:55
  • but your method may not work. For example. 5 * 5 * 5. It will first do 5 * 5. Send it out. The do 5 * 5. Which will be 50 not 125. At least that's what I think – Eric Apr 03 '11 at 17:29
  • I don't have ESP ;) Your example and question didn't specify you'd have multiple operations. One sec ... – Brian Roach Apr 03 '11 at 17:33
  • @Brian Roach wait lol, one more problem, i need to do passes (because i need multiplication/division first then adding/subtracting) should i make two functions? – Eric Apr 04 '11 at 01:02
  • I got it to work! I used your first function above with some modification. Thank you for all your help :) – Eric Apr 04 '11 at 01:27
  • See, now you're making it more complicated :-p That's a slightly more complicated problem but you can still use the same recursive approach; you have to sort of branch off when you hit a `+` or minus `-`. I can poke at it later, but the initial iterative approach of modifying the array in place will work (and my first example does that), it's just slightly more expensive since you are modifying the array size and would have to go through it twice. – Brian Roach Apr 04 '11 at 01:28
  • Don't know if you're still out there, but I edited to show how you can do this recursively without all the array modification :) Cheers! – Brian Roach Apr 04 '11 at 16:50
  • Thanks for all the help. I will try it out! but from reading it, I have no idea how it works lol :P – Eric Apr 07 '11 at 01:59
0

Why modify the input array when you could use the input array as read-only and create output ArrayLists (or better stacks)?

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Lol. No idea how to do that. Because then I'd have to iterate through each new array. I'm still new to this stuff :). – Eric Apr 03 '11 at 16:35
  • You're trying to modify an array or collection from within a for loop which is a recipe for disaster -- unless you can delete the item with an Iterator. Better to simply loop through the collection and extract the information out of it as you loop, placing it into a stack (or two -- one for operators, one for numbers) which is just another collection. – Hovercraft Full Of Eels Apr 03 '11 at 16:37
0

I think that if you use a dynamic structure, such as an ArrayList, you should be able to fix that problem.

According to this:

The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically.

and this previous SO post, using a dynamic data structure should solve your problem, I think that the same mechanism applies for when you remove, as well as add, elements from the list. You might however, need to implement some mechanism to keep track of where the items are after each and every replacement you make.

Community
  • 1
  • 1
npinti
  • 51,780
  • 5
  • 72
  • 96