-2

How can I create a better solution without stacks or otherwise optimize this code.

import java.util.*;

public class Calc
{

    // (15+25)+((15+25)+5)


    public static String calc(String a, String b, String operator){


            switch (operator) {

                    case "+": return Double.valueOf(a) + Double.valueOf(b)+"";

                    case "~": return Double.valueOf(a) - Double.valueOf(b)+"";

                    case "*": return Double.valueOf(a) * Double.valueOf(b)+"";

                    case "/": return Double.valueOf(a) / Double.valueOf(b)+"";

                }

            return null;

        }


    //difference with operator '-'..i replace this operator to ~

    public static String minustotild(String s){

            String result = ""+s.charAt(0);

            for (int i = 1; i < s.length(); i++){

                    if ((s.charAt(i) == '-') && ("+-*(/~".indexOf(s.charAt(i-1)) == -1))   // if previous char is not a symbol( is digit)

                        result += ""+'~';

                    else result +=""+s.charAt(i);

                }

            return result;

        }

    public static String operate(String expression){


            String num[];   int index = -1;  
            Character priorityOperator='/';  // default
            String operators;
            while (!((  operators = expression.replaceAll("[^*+/~]","")  ).isEmpty()))     // while have operator..
                {   

                    if ( (index = operators.indexOf('/')) == -1){        // choose priority operator
                        priorityOperator = '*';
                        if  ( (index = operators.indexOf('*')) == -1){
                                priorityOperator=operators.charAt(0);
                                index = operators.indexOf(priorityOperator);
                            }
                    }
                    num = expression.split("[^0-9\\-.]"); // сплитим все числа..

                    // заменяем строкое представление арифметики,на строковой результат с помощью калк(). 
                    expression=expression.replaceFirst(num[index]+"\\"+priorityOperator+num[index+1], calc(num[index],num[index+1],""+priorityOperator)); 

                }

            return expression;

        }


    public static String operateBracket(StringBuilder s, int startIndex){
            // ''
            // 3+4+(4+(3+3)+5)+(4+)
            if (startIndex == -1) {        // если скобок нету то оперируем .
                    return (operate(s.toString()));
                }
            else {   
                    int k = 1;
                    for (int i=startIndex+1; i < s.length(); i++){

                        if (s.charAt(i) == '(')  
                                k++;
                            else if ((s.charAt(i) == ')')) 
                                {
                                    if (k == 1) {    // нашли конец первой скобки. не знаю как лучше сделать)

                                            String newBracket = s.substring(startIndex+1, i);

                                            s=s.replace(startIndex,i+1,operateBracket(new StringBuilder(newBracket), newBracket.indexOf(""+'(')));

                                        }
                                    k--;
                                }

                        }
                }

            return operate(s.toString());

        }





    public static void main(String[] args){

        Scanner s = new Scanner( System.in );
        String b = s.next();

             do  {

                   StringBuilder a = new StringBuilder(minustotild(b));
                   System.out.println(" result = "+operateBracket(a,a.indexOf(""+'(')));

              }   while ( (b = s.next()) != "null");


        }

}
John Powell
  • 12,253
  • 6
  • 59
  • 67
aquavita_x
  • 41
  • 1
  • 7
  • 1
    You seem to imply this code is working essentially but just want an optimised version? Because there is no problem in the code this post is arguably off-topic for SO –  Feb 21 '15 at 19:36
  • yes :) also without java language dependency..however i think about general solution,not scripts or another library ,and etc :) – aquavita_x Feb 22 '15 at 06:29
  • returning null, unless for specific reasons, is typically a bad idea. Return empty String instead. – hfontanez Feb 22 '15 at 14:39
  • I'm voting to close this question as off-topic because it belongs on http://codereview.stackexchange.com – Bart Kiers Feb 22 '15 at 14:44
  • 1
    @BartKiers This isn't a perfect fit for Code Review, though it might be okay. But whether or not something is on-topic on Code Review should not impact whether or not you vote to close here on Stack Overflow. The only reason to vote to close a question here on Stack Overflow is because it is off-topic on Stack Overflow. Questions that are on-topic on other Stack Exchange sites are not inherently off-topic here. – nhgrif Feb 22 '15 at 15:13
  • @BartKiers, I agree with nhgrif. In accordance with SO guidelines, it is perfectly OK to ask about coding techniques, which this question falls under. – hfontanez Feb 22 '15 at 15:17

1 Answers1

0

First, you can create an Operation interface:

public interface Operation
{
    double apply(double x, double y);
}

Then, you create your concrete operations:

public enum BasicOperation implements Operation
{
    PLUS("+") {
        public double apply(double x, double y) { return x + y; }
    },
    MINUS("-") {
        public double apply(double x, double y) { return x - y; }
    },
    TIMES("*") {
        public double apply(double x, double y) { return x * y; }
    },
    DIVIDE("/") {
        public double apply(double x, double y) { return x / y; }
    };

    private final String symbol;
    BasicOperation(String symbol)
    {
        this.symbol = symbol;
    }

    @Override
    public String toString()
    {
        return symbol;
    }
}

And then you create your logic to use these operations:

public class ExtensibleEnumOperationTest
{
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter a number (i.e. 1.43): ");
        double x = input.nextDouble();
        System.out.print("Enter another number: ");
        double y = input.nextDouble();
        input.close();
        System.out.println();
        System.out.println("Testing Basic Operations using Bounded Type Token (Item 29)");
        test(BasicOperation.class, x, y);

        System.out.println("Testing Basic Operations using Bounded Wildcard Type (Item 28)");
        test(Arrays.asList(BasicOperation.values()), x, y);

        System.out.println("Testing a single operation:");
        Operation op = BasicOperation.PLUS;
        System.out.println(x + " + " + y + " = " + op.apply(x, y));     
    }

    private static <T extends Enum<T> & Operation> void test(Class<T> opSet,
        double x, double y)
    {
        for (Operation op : opSet.getEnumConstants())
            System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
        System.out.println();
    }

    private static void test(Collection<? extends Operation> opSet, double x,
            double y)
    {
        for (Operation op : opSet)
            System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
        System.out.println();
    }
}

This should work well. In addition, it will allow you to expand your operations by creating another enum that implements Operation. For instance, exponent or remainder. This code was taken from the book Effective Java Item 39

hfontanez
  • 5,774
  • 2
  • 25
  • 37
  • thanks i test it :) but minimum language speciality need. in other words, algorytm solution . with standart capabilities – aquavita_x Feb 22 '15 at 07:25
  • @aquavita_x what part is non-standard? Enumerations have been part of Java since Java 5. This isn't about algorithms. If anything, using the character '~' for subtraction is non-standard. IF you want a simpler solution, take the enum and place it inside your test class (with main method). The problem is that the solution will not be extendable. – hfontanez Feb 22 '15 at 14:37