-3

I looked around a bit for a solution to parsing out a chemical formula that contained molecular components that may have their own suffixes for the purposes of being able to parse a formula for its complete atomic fraction.

How would one do this in Java?

Captain Prinny
  • 459
  • 8
  • 23

1 Answers1

0

Not having been able to find a way to do this in short order (and not having done a fun algorithm in a while) I settled on a stack implementation, as it's actually less complicated than a math operation stack.

Going backward through the stack, you only have to be aware of a few things, as this is fundamentally a modified implementation of a common solution to parsing a mathematical statement.

1) Your integer suffix can be built of multiple characters
2) Your integer suffix could be a multiplier (next character being a ")")
3) You need to handle for implicit "1"s

The implementation pops characters off one stack and pushes only letters and numbers onto your "return stack".

String expandFormula(String s){
    Stack<Character> stack = new Stack();
    Stack<Character> hanoi = new Stack();
    char[] ca = s.toCharArray();
    Character c;
    List<Integer> multipliers = new ArrayList();
    String multiBuff;

    int val;
    boolean flag;

    for (int i = 0; i < ca.length; i++)
        stack.push(ca[i]);

    while(!stack.isEmpty()){
        c = stack.pop();
        if (Character.isLetter(c)){ 
            try{
                //previous parse was end of Symbol, implicit "1"
                flag = Character.isUpperCase(hanoi.peek());
            }
            catch(EmptyStackException ese){ //change exception
                flag = false;
            }
            //push implicit 1
            if (flag){
                stack.push(c);
                stack.push('1');
            }
            //continue as usual
            else
                hanoi.push(c);
        }
        //begin number parsing
    else if(Character.isDigit(c)){
            flag = false;
            multiBuff = c +"";
            //parse the integer out
            while(Character.isDigit(stack.peek())){
                c = stack.pop();
                multiBuff = c + multiBuff;
            }
            //if next char is ), then value is a suffix
            if (stack.peek() == ')'){
                flag = true;
                stack.pop();
                multipliers.add(Integer.parseInt(multiBuff));
                //pop successive )s
                while(stack.peek() == ')'){
                    stack.pop();
                    multipliers.add(1);
                }
            }
            if(Character.isLetter(stack.peek())){
                val = flag ? 0 : Integer.parseInt(multiBuff);
                //get full value of 
                for(Integer i : multipliers){
                    if (val == 0)
                        val = i;
                    else
                        val *= i;
                }
                //trim and push first decibit
                while(val > 0){
                        hanoi.push(Character.forDigit(val % 10, 10));
                        val /= 10;
                }
            }
        }
        //end of nest, remove most recent multiplier
        else if(c == '(')
            try{
                multipliers.remove(multipliers.size()-1);
            }
            catch(ArrayIndexOutOfBoundsException aioobe){

            }
    }
    multiBuff = "";
    while(!hanoi.isEmpty())
        multiBuff += hanoi.pop();

    return multibuff;        
}

This solution can be converted directly to your output string by:

1) Change "hanoi" to string
2) Change "hanoi.push(c)" to hanoi = c + hanoi
3) Change "hanoi.peek()" to "hanoi.charAt(0)"
4) Change Exceptions as necessary (or use general exceptions anyway)
5) Just return hanoi instead of the multibuff thing at the bottom.

Captain Prinny
  • 459
  • 8
  • 23