package de.janchristiangruenhage.math.addition; import de.janchristiangruenhage.math.Number; import java.util.LinkedList; public class Addition { private LinkedList addends; private int splitLines; private String printedCalculation; private String result; private int resultLength; private boolean cutResult; private String resultCarry; private boolean calculated; private int lineLength; /** * Constructs a new Addition. * * @param addends The Addends * @param splitLines After how many lines an additional Result will be calculated * @param resultLength How many digits the result should have, for overflow or a carry * see cutResult * @param cutResult If the result should be cut * @param lineLength How long each line should be */ public Addition(LinkedList addends, int splitLines, int resultLength, boolean cutResult, int lineLength) { this.addends = addends; this.splitLines = splitLines; this.resultLength = resultLength; this.cutResult = cutResult; this.lineLength = lineLength; } /** * Creates an easily readable Addition and returns it. * * @return String representation of the Calculation */ public String printCalculation() { if (calculated) { return printedCalculation; } if (splitLines != 0 && splitLines < addends.size()) { //decides whether the Addition has to be split before Calculation //throw new FeatureNotImplementedYetException(); //Throws new Feature not Implemented Yet Exception return splitAndPrint(); //splits and prints the calculation, not working yet } else { return print(); //just prints the calculation } } /** * Creates an easily readable Addition and returns it. * This is used if the Addition doesn't have to be split anymore * * @return String representation of the Calculation */ private String print() { int maximum = 0; //Variable for the Maximum Length of a Addend String LinkedList shortenedAddends = new LinkedList<>(); for (String addend : addends) { shortenedAddends.add(addend.substring(1).trim()); //The substring for removing the plus symbol at the beginning, the trimming for removing unnecessary spaces maximum = (shortenedAddends.getLast().length() > maximum) ? //Checks whether the length of the i-th String is higher than the maximum variable shortenedAddends.getLast().length() : maximum; //Assigns the maximum the correct value, the string length if its bigger, itself otherwise } result = ""; //Constructs the new String where the result will be saved in String carries = "0"; //Constructs the new String where the carries will be saved in int carry = 0; //New variable for the carry at the point of the calculation for (int i = 0; i < maximum; i++) { AdditionColumn additionColumn = new AdditionColumn(shortenedAddends, carries, carry, i).invoke(); //Method-Object for calculating a single column of the addition carries = additionColumn.getCarries(); //Get the carries string from the Method-Object carry = additionColumn.getCarry(); //Get the carry from the Method-Object } if (carry != 0) { result = carry + result; } String retVal = ""; //Construct the retVal String where the calculation wil be put into for (String addend : shortenedAddends) { retVal = addAddend(retVal, addend); //Adds the addend to the retVal string in a new line } for (int i = 0; i < lineLength; i++) { retVal += " "; //Adds a line of spaces } retVal += "\n"; //Adds a new line while (carries.length() > 0 && carries.charAt(0) == '0') { carries = carries.substring(1, carries.length()); //removes leading zeroes from the carries string } if (cutResult && carries.length() > resultLength) { carries = "(" + carries.substring(0, carries.length() - resultLength) + ")" + carries.substring(carries.length() - resultLength); //adds braces around the cut part of the result, if wanted } while (carries.length() < lineLength - 1) { carries = " " + carries; //elongates the carries string with spaces } carries = "+" + carries; //adds the plus symbol to the carries string retVal += carries + "\n"; //adds the carries string to the retVal string in a new line for (int i = 0; i < lineLength; i++) { retVal += "_"; //draws a line } retVal += "\n"; //adds new line if (cutResult && result.length() > resultLength) { resultCarry = result.substring(0, result.length() - resultLength); //cuts the carry from the result result = "(" + resultCarry + ")" + result.substring(result.length() - resultLength); //adds braces around the carry } while (result.length() <= lineLength - 1) { result = " " + result; //elongates the result string } retVal += result; //adds the result to the retVal string retVal += "\n\n"; //adds four new lines after the calculation printedCalculation = retVal; //saving the printed calculation for later usage calculated = true; //sets calculated to true, that the result doesn't have to be recalculated if it is needed again return retVal; } private String addAddend(String retVal, String addend) { String addendCopy = addend; while (addendCopy.length() > 0 && addendCopy.charAt(0) == '0') { addendCopy = addendCopy.substring(1, addendCopy.length()); //cuts leading zeroes } if (addendCopy.length() == 0) { return retVal; //skips the addend, if it is zero and therefore an empty line } if (cutResult && addend.length() > resultLength) { addendCopy = "(" + addend.substring(0, addend.length() - resultLength) + ")" + addend.substring(addend.length() - resultLength); //adds braces around the cut part of the addend } while (addendCopy.length() < lineLength - 1) { addendCopy = " " + addendCopy; //elongates the addend with spaces } addendCopy = "+" + addendCopy; //adds a plus symbol in front of the addend retVal += addendCopy; //adds the addend to the retVal string retVal += "\n"; //adds a new line to the retVal string return retVal; } /** * TODO: Not Working ATM *

* Creates an easily readable Addition and returns it. * This first splits the Additions and then calls their printCalculation() Method * it is therefore an indirect recursion, since this method is only called by the * printCalculation() Method. * * @return String representation of the Calculation */ private String splitAndPrint() { LinkedList additions = new LinkedList<>(); int carryLine = 0; while (addends.size() > 0) { LinkedList addends = new LinkedList<>(); if (carryLine != 0) { String intermediateResult = additions.getLast().calculateResult(); if (cutResult) { intermediateResult = intermediateResult.replaceFirst("\\(", ""); intermediateResult = intermediateResult.replaceFirst("\\)", ""); } addends.add(intermediateResult); } for (int i = 0; i < splitLines - carryLine; i++) { addends.add(this.addends.removeFirst()); if (this.addends.size() == 0) { break; } } additions.add(new Addition(addends, splitLines, resultLength, cutResult, lineLength)); carryLine = 1; } String retVal = ""; for (Addition addition : additions) { retVal += addition.printCalculation(); } resultCarry = additions.getLast().getResultCarry(); result = additions.getLast().calculateResult(); return retVal; } /** * Calculator for the Result * * @return the Result */ private String calculateResult() { printCalculation(); return result; } /** * Getter for the ResultCarry, which is the Carry of the Result * * @return the ResultCarry */ public String getResultCarry() { return resultCarry; } /** * The Class AdditionColumn represents one Column of the Addition */ private class AdditionColumn { private LinkedList shortenedAddends; private String carries; private int carry; private int i; /** * Constructs a new AdditionColumn * * @param shortenedAddends The Addend Strings, * without additional spacing and the plus symbol * @param carries The String of Carries * @param carry The Carry for this column * @param i which column of the Addends should be used */ public AdditionColumn(LinkedList shortenedAddends, String carries, int carry, int i) { this.shortenedAddends = shortenedAddends; this.carries = carries; this.carry = carry; this.i = i; } /** * Getter for the Carries * * @return the carries */ public String getCarries() { return carries; } /** * Getter for the Carry * * @return the Carry */ public int getCarry() { return carry; } public AdditionColumn invoke() { Number resultNum = new Number(0); for (String addend : shortenedAddends) { if ((addend.length() - i - 1) >= 0) { resultNum.add(Number.parseNumber(addend.charAt(addend.length() - i - 1))); } } resultNum.add(new Number(carry)); carry = resultNum.getCarry(); Number carryNum = new Number(carry); carries = carryNum.getNumber() + carries; result = resultNum.getNumber() + result; return this; } } }