Place +,-, nothing between 1, 2, …, 9 (in this order) whose sum is 100

I am trying to solve a programming problem and I see the size of program has increased a bit while I keep coding. I found this problem here.
Here is the problem:
Write a program that outputs all possibilities to put + or - or nothing between the numbers 1, 2, ..., 9 (in this order) such that the result is always 100. For example: 1 + 2 + 34 – 5 + 67 – 8 + 9 = 100.
I coded it in Java.
Here is the complete program.
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * Write a program that outputs all possibilities to put + or -
 * or nothing between the numbers 1, 2, ..., 9 (in this order)
 * such that the result is always 100. For example: 1 + 2 + 34 – 5 + 67 – 8 + 9 = 100.
 */
/**
 * @author srk
 */

public class Problem5 {

    private final int START_INDEX = 0;
    private final String LEFT_SQUARE_BRACE = "[";
    private final String RIGHT_SQUARE_BRACE = "]";
    private final String SPLIT_STRING_REGEX = ",";
    private final String STRING_SUFFIX = ",";
    private final List<String> OPERATIONS = Arrays.asList("+", "-", "");

    public static void main(String[] args) {
        Problem5 problem5 = new Problem5();

        List<Integer> oneToNine = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        int resultantSum = 100;
        /* Step 1: Break it into functions */
        LinkedHashMap<String, List<StringBuilder>> fBreakUp = problem5
                .breakIntoFunctions(new ArrayList<>(oneToNine),
                        new LinkedHashMap<String, List<StringBuilder>>());
        /* Step2: Resolve each function from bottom up */
        problem5.workFromBottomUp(problem5.fBreakUpKeysFrmTail(fBreakUp),
                fBreakUp);
        /*
         * Step3: Evaluate all the combinations and fetch only those, whose sum
         * is 100
         */
        List<StringBuilder> allcombinations = fBreakUp.get(problem5
                .getfunction(oneToNine));
        System.out.println("Probable combinations -> " + allcombinations.size());
        List<String> specCombinations = problem5.getSpecCombinations(
                allcombinations, resultantSum);
        problem5.printResult(specCombinations);
    }

    private void printResult(List<String> specCombinations) {
        for (String combination : specCombinations) {
            System.out.println(combination);
        }
        System.out.println("Total combinations " + specCombinations.size());

    }

    private List<String> getSpecCombinations(
            List<StringBuilder> allcombinations, int resultantSum) {
        List<String> finalCombi = new ArrayList<>();

        for (StringBuilder csv : allcombinations) {
            for (String thisCombi : csv.toString().split(SPLIT_STRING_REGEX)) {
                if (findSum(thisCombi).compareTo(
                        BigInteger.valueOf(resultantSum)) == 0) {
                    finalCombi.add(thisCombi);
                }
            }
        }
        return finalCombi;

    }

    private static BigInteger findSum(String input) {
        /* Step1 : Split with + */
        String[] positives = input.split("[+]+");
        List<BigInteger> ListAfterExpEval = new ArrayList<>();
        for (String thisPosExp : positives) {
            BigInteger expValue = BigInteger.ZERO;
            if (thisPosExp.contains("-")) {
                /* Split with -, if it has */
                String[] negatives = thisPosExp.split("[-]+");
                for (String thisNegExp : negatives) {
                    /* Covert String to BigInteger */
                    BigInteger thisNumber = new BigInteger(thisNegExp);
                    if (expValue == BigInteger.ZERO) {
                        expValue = thisNumber;
                    } else {
                        expValue = expValue.subtract(thisNumber);
                    }
                }
                ListAfterExpEval.add(expValue);
            } else {
                /* could be a number */
                ListAfterExpEval.add(new BigInteger(thisPosExp));
            }

        }
        BigInteger finalSum = BigInteger.ZERO;
        for (BigInteger thisNum : ListAfterExpEval) {
            if (finalSum == BigInteger.ZERO) {
                finalSum = thisNum;
            } else {
                finalSum = finalSum.add(thisNum);
            }

        }
        return finalSum;
    }

    private void workFromBottomUp(List<String> fBreakUpKeys,
            LinkedHashMap<String, List<StringBuilder>> fBreakUp) {
        String tailKeyInFBreakUp = fBreakUpKeys.remove(START_INDEX);
        Iterator<String> fBreakUpKeysItr = fBreakUpKeys.iterator();
        String keyBeforeTail;
        while (fBreakUpKeysItr.hasNext()) {
            keyBeforeTail = fBreakUpKeysItr.next();
            fBreakUpKeysItr.remove();
            tailKeyInFBreakUp = resolveFunctions(tailKeyInFBreakUp,
                    keyBeforeTail, fBreakUp);
        }

    }

    private String resolveFunctions(String tailKeyInFBreakUp,
            String keyBeforeTail,
            LinkedHashMap<String, List<StringBuilder>> fBreakUp) {
        List<StringBuilder> fValToBeSubstituted = fBreakUp
                .get(tailKeyInFBreakUp);
        List<StringBuilder> fValsToBeResolved = fBreakUp.get(keyBeforeTail);
        for (StringBuilder fValToBeResolved : fValsToBeResolved) {
            int indexOfF = fValToBeResolved.indexOf(tailKeyInFBreakUp);
            if (indexOfF != -1) {
                fValToBeResolved.replace(indexOfF, fValToBeResolved.length(),
                        fValToBeSubstituted.toString());
                fValToBeResolved.replace(START_INDEX,
                        fValToBeResolved.length(),
                        cartesianProduct(fValToBeResolved));
            }
        }
        fBreakUp.remove(tailKeyInFBreakUp);
        return keyBeforeTail;
    }

    private String cartesianProduct(StringBuilder fValToBeResolved) {
        StringBuilder localSb = new StringBuilder();
        int indexOfLeftSqBrace = fValToBeResolved.indexOf(LEFT_SQUARE_BRACE);
        int indexOfRightSqBrace = fValToBeResolved.indexOf(RIGHT_SQUARE_BRACE);
        String prefix = fValToBeResolved.substring(START_INDEX,
                indexOfLeftSqBrace);
        List<String> resolvedVals = Arrays.asList(fValToBeResolved.substring(
                indexOfLeftSqBrace + 1, indexOfRightSqBrace).split(
                SPLIT_STRING_REGEX));
        for (String val : resolvedVals) {
            localSb.append(prefix.trim() + val.trim());
            if (resolvedVals.indexOf(val) != resolvedVals.size() - 1) {
                localSb.append(STRING_SUFFIX);
            }
        }
        return localSb.toString();
    }

    private List<String> fBreakUpKeysFrmTail(
            LinkedHashMap<String, List<StringBuilder>> fBreakUp) {
        List<String> functionsBreakUpKeys = new ArrayList<>(fBreakUp.keySet());
        Collections.reverse(functionsBreakUpKeys);
        return functionsBreakUpKeys;
    }

    private LinkedHashMap<String, List<StringBuilder>> breakIntoFunctions(
            List<Integer> workList,
            LinkedHashMap<String, List<StringBuilder>> fBreakUp) {

        String function = getfunction(workList);
        String head = getHeadAndRemoveit(workList);

        boolean workListSizeIsOne = workList.size() == 1 ? true : false;
        ArrayList<StringBuilder> breakDownValues = new ArrayList<>();

        for (String operation : OPERATIONS) {
            StringBuilder sb = new StringBuilder();
            if (!(workListSizeIsOne ? breakDownValues.add(sb.append(head
                    + operation + workList.get(START_INDEX))) : breakDownValues
                    .add(sb.append(head + operation + getfunction(workList)))))
                break;

        }
        fBreakUp.put(function, breakDownValues);

        if (!workList.isEmpty() && !workListSizeIsOne)
            breakIntoFunctions(workList, fBreakUp);

        return fBreakUp;
    }

    private String getHeadAndRemoveit(List<Integer> workList) {
        Integer headElement = workList.get(START_INDEX);
        workList.remove(headElement);
        return String.valueOf(headElement);
    }

    private String getfunction(List<Integer> list) {
        StringBuilder sb = new StringBuilder("f(");
        for (Integer integ : list) {
            sb.append(integ);
        }
        return sb.append(")").toString();
    }

}
What are the points, where it could be improved and optimized?

Комментарии

Популярные сообщения из этого блога

FillChar and StringOfChar under Delphi 10.2 for Win64 Release Target

Intuition behind successive squaring.