Optimizing program to output all numbers summing to 100 I just finished my program which calculates the solutions to this problem:


  Outputs all possibilities to put + or - or nothing between the numbers 1,2,…,9 (in this order) such that the result is 100.


Code in question:

package defaultpackage;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

class Main {
    static int[] pos_counter = {0,0,0,0,0,0,0,0};

    static Boolean running = true;

    public static void main(String[] args) {
        int counter = 0;

        while(running) {
            increment();
            oobcheck();
            try {
                counter = (int) calculate(printeq());
            } catch (ScriptException e2) {
                e2.printStackTrace();
            }
            if(counter==100) {
                System.out.print(printeq());
                System.out.print("=");
                System.out.println(100);
            }
        }
    }

    public static int[] increment(){
        int stepcounter = 7;
        pos_counter[7]++;
        while(stepcounter&gt;= 0&amp;&amp;running){

            if(pos_counter[stepcounter]==3&amp;&amp;running){
                if(stepcounter-1 == -1){
                    running = false;
                } else{
                    pos_counter[stepcounter-1]++;
                    pos_counter[stepcounter]=0;
                }
            }
            stepcounter--;
        }
        return pos_counter;
    }

    public static double calculate(String s) throws ScriptException{
        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine engine = mgr.getEngineByName("JavaScript");
        return (double) engine.eval(s);
    }

    public static void readout() {
        int stepcounter = 0;
        while(stepcounter &lt;= 7) {
            System.out.print(pos_counter[stepcounter]);
            stepcounter++;
        }
        System.out.println("");
    }

    public static String printeq() {
        int stepcounter = 0;
        String read = "";
        while(stepcounter &lt;= 7) {
            read = "" + read + (stepcounter+1);
            if(pos_counter[stepcounter] == 0){
            }else if(pos_counter[stepcounter] == 1) {
                read = read + "+";
            }else if(pos_counter[stepcounter] == 2) {
                read = read + "-";
            }
            stepcounter++;
        }
        read = read + "9";
        return read;
    }

    public static void oobcheck(){
        int stepcounter = 0;
        Boolean checker = true;
        while(checker&amp;&amp;stepcounter &lt;= 7) {
            if(pos_counter[stepcounter] == 2) {
                stepcounter++;
                checker = true;
            }else{
                checker = false;
            }
            if(stepcounter==7){
                if(pos_counter[7] == 2) {
                    running = false;
                }
            }
        }
    }
}


My program works fine and spits out all the answers correctly but I'm looking to improve it. I've seen solutions to similar problems and they mostly take up less space or seem more organized.

Concrete questions:


Where can I learn to improve code efficiency or organization?
What could be used specifically to make my code faster and more efficient?
General remark

Short code (as in less space in code) is not necessarily easier to read, nor does it need to be faster. You can try to keep removing unnecessary stuff until it is as short as possible, but please keep it readable. Writing code is hard, reading code is twice as hard. 

Short answer


Online, everywhere, in books. "Effective Java" for example. Read about algorithms and data structures. Look at how others solved problems. Read many code reviews.
Use a profiler and measure where your code is slow.


Longer answer


You need to expose yourself to a lot of code, and start with simple problems. See how you would solve it, then look how others solved it and try to improve upon it.
For this case: try to represent your operators and operands in such a way that you can evaluate them in Java.  Generally: use the correct data structures and algorithms. That is most important. Then, try to use the right types. String concatenation is generally a lot slower in execution time than integer math. 


Example

For example to evaluate and generate the permutations (using recursion just because we can :):

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MakeHundred {

    private static int LENGTH = 8;

    // Encode the operators in a enum. We use the factor to implement
    // easier operation later on, and the display String as well.

    enum Operator {

        PLUS(1, "+"), MINUS(-1, "-"), NONE(0, "");

        private int factor;
        private String display;

        public String getDisplay() {
            return display;
        }

        Operator(int factor, String display) {
            this.factor = factor;
            this.display = display;
        }

        public int getFactor() {
            return factor;
        }

    }

    /**
     * Class for keeping a permutation, with is an list of operators which will be
     * used to create a sum, eg. 1 op1 2 op2 3.
     * 
     * @author RobAu
     *
     */
    public static class Permutation {

        Operator[] operators;

        // Just one operator
        public Permutation(Operator operator) {
            this.operators = new Operator[] { operator };
        }

        // Copy the given permutation, append the given operator
        public Permutation(Permutation sourcePermutation, Operator operatorToAppend) {
            this.operators = Arrays.copyOf(sourcePermutation.operators, sourcePermutation.operators.length + 1);
            this.operators[sourcePermutation.operators.length] = operatorToAppend;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i &lt; operators.length; i++) {
                sb.append(i + 1);
                sb.append(operators[i].getDisplay());
            }
            // append the last digit
            sb.append(operators.length + 1);
            return sb.toString();
        }

        public int evaluate() {
            int index = 0;
            int currentNumber = 0;
            int total = 0;

            // We start with a previous operator (+),
            // So the code becomes simpler.
            // 1+2 = 0 + 1 + 2.
            Operator operator = Operator.PLUS;

            while (index &lt; LENGTH) {

                currentNumber += (index + 1);

                // If there is no operator, we are making a bigger number.
                if (operators[index] == Operator.NONE) {
                    currentNumber *= 10;
                } else {

                    // We increate the total by adding the current Number
                    // and using the previously seen operator
                    total += currentNumber * operator.getFactor();
                    currentNumber = 0;
                    operator = operators[index];
                }
                index++;
            }

            // add the last number.
            currentNumber += index + 1;
            total += currentNumber * operator.getFactor();

            return total;
        }

        /**
         * Generate all permutation with length &lt;code&gt;length&lt;/code&gt;
         */
        public static List&lt;Permutation&gt; generate(int length) {
            return generate(null, length);
        }

        private static List&lt;Permutation&gt; generate(List&lt;Permutation&gt; permutations, int length) {

            List&lt;Permutation&gt; perms = new ArrayList&lt;&gt;();
            if (length == 1) {
                for (Operator o : Operator.values()) {
                    perms.add(new Permutation(o));
                }
            } else {
                for (Permutation p : generate(permutations, length - 1)) {
                    for (Operator o : Operator.values()) {
                        perms.add(new Permutation(p, o));
                    }
                }
            }
            return perms;
        }
    }

    public static void main(String[] args) {
        for (Permutation p : Permutation.generate(null, LENGTH)) {
            if (p.evaluate() == 100) {
                System.out.println(p);
            }
        }
    }
}


Including JVM startup this runs in:

real    0m0,088s
user    0m0,088s
sys 0m0,012s