String Calculator multiple delimiters
Assignment description: The code is for a String Calculator. Your job is to refactor the code so its readable, supportable, and to resolve any bugs. Below will be a description of what the code is trying to do and new functionality that you must add. All your code must be supported by JUnits. There are three existing JUnits that currently pass and must continue to pass after you complete the coding exercise. We are looking to see how you refactor code, your interpretation on what makes code readable and supportable, and how you write unit tests. Treat this code as production so do not delete or change the signatures of any of the public methods, unless you are changing it to throw exceptions. We are using Java 5 and JUnit 4. Please follow the directions exactly.
What the code is trying to do
- The add, subtract, and multiply methods take in a String containing numbers delimited by either a comma and/or new line character.
- The method returns the result as an int.
- You can have one or both of the delimiters in the String. For example, the following are all correct “1,2” “1\n2” “1,2\n3”
- If you pass in an empty String, then the result should be 0.
New functionality to add
- Modify all three methods add, subtract, and multiply to add the ability to change the delimiter. To change the delimiter, the beginning of the string will contain a separate line that looks like this: “//[delimiter]\n[numbers…]”. For example “//;\n1;2” should return three where the default delimiter is ‘;’ . Changing the delimiter is optional and all other functionality must still work.
- Calling the methods with a negative number will throw an exception “negatives not allowed” – and the negative that was passed. If there are multiple negatives, show all of them in the exception message.
Existing java code:
import java.util.StringTokenizer; public class StringCalculator { public int add(String s) { int u = 0; StringTokenizer st = new StringTokenizer(s, ","); while (st.hasMoreTokens()) { String t = st.nextToken(); Integer i = new Integer(t); u = u + i; } if (u == 0) { StringTokenizer st2 = new StringTokenizer(s, "\n"); while (st2.hasMoreTokens()) { String t = st2.nextToken(); Integer i = new Integer(t); u = u + i; } } return u; } private int sum(String s) { int u = 0; String[] a = s.split(","); for (int i = 0; i < a.length; i++) { u += new Integer(a[i]); } return u; } public int subtract(String s) { int u = 0; StringTokenizer st = new StringTokenizer(s, ","); while (st.hasMoreTokens()) { String t = st.nextToken(); Integer i = new Integer(t); if (u ==0) u=i; else u = u - i; } if (u == 0) { StringTokenizer st2 = new StringTokenizer(s, "\n"); while (st2.hasMoreTokens()) { String t = st2.nextToken(); Integer i = new Integer(t); if (u ==0) u=i; else u = u - i; } } return u; } public int multiply(String s) { int u = 0; StringTokenizer st = new StringTokenizer(s, ","); while (st.hasMoreTokens()) { String t = st.nextToken(); Integer i = new Integer(t); if (u ==0) u=i; else u = u * i; } if (u == 0) { StringTokenizer st2 = new StringTokenizer(s, "\n"); while (st2.hasMoreTokens()) { String t = st2.nextToken(); Integer i = new Integer(t); if (u ==0) u=i; else u = u + i; } } return u; } }
Solution:
Java Code:
import java.util.ArrayList; import java.util.List; /** * * @author Java Honk * */ public class StringCalculator { public static void main(String args[]){ StringCalculator stringCalculator = new StringCalculator(); System.out.println("Add result: " + stringCalculator.add("1\n;2;3")); System.out.println("Subtraction result: " + stringCalculator.subtract("1\n;2;3")); System.out.println("Multiply result: " + stringCalculator.multiply("1\n;2;3")); } /** * @param s * @return Integer * @throws RuntimeException */ public int add(String s) throws RuntimeException { int returnValue = 0; if (null != s && s.equals("")) { return returnValue; } List<Integer> inputIntegerList = splitStringInputValue(s); for (Integer integer : inputIntegerList) { returnValue = returnValue + integer; } return returnValue; } /** * @param s * @return Integer * @throws RuntimeException */ public int subtract(String s) throws RuntimeException { int returnValue = 0; if (null != s && s.equals("")) { return returnValue; } List<Integer> inputIntegerList = splitStringInputValue(s); for (int i = 0; i < inputIntegerList.size(); i++) { Integer integer = inputIntegerList.get(i); if (i == 0) { returnValue = integer; } else { returnValue = returnValue - integer; } } return returnValue; } /** * @param s * @return Integer * @throws RuntimeException */ public int multiply(String s) throws RuntimeException { int returnValue = 1; if (null != s && s.equals("")) { return 0; } List<Integer> inputIntegerList = splitStringInputValue(s); for (Integer integer : inputIntegerList) { returnValue = returnValue * integer; } return returnValue; } /** * @param inputValue * @return Integer * @throws RuntimeException */ public List<Integer> splitStringInputValue(String inputValue) throws RuntimeException { String stringArray[] = inputValue .split("[//\n,!.?:;@#$%^&*()_+=?'<>+]"); List<Integer> list = new ArrayList<Integer>(); for (int i = 0; i < stringArray.length; i++) { String string = stringArray[i]; if (null != string && !string.equals("")) { if (isInteger(string)) { list.add(Integer.parseInt(string)); } } } StringBuilder negativeValue = new StringBuilder(); for (Integer integer : list) { if (integer < 0) negativeValue.append(integer + " "); } if (!negativeValue.toString().equals("")) { throw new RuntimeException( "Negatives not allowed. Negative values: " + negativeValue.toString()); } return list; } /** * @param inputValue * @return Integer */ public static boolean isInteger(String inputValue) { try { Integer.parseInt(inputValue); return true; } catch (NumberFormatException nfe) { return false; } } }
Output:
JUnit Test class:
import org.junit.Assert; import org.junit.Test; public class StringCalculatorTest { @Test public void addNumbers() { StringCalculator calculator = new StringCalculator(); Assert.assertEquals(5, calculator.add("2,3")); Assert.assertEquals(0, calculator.add("")); Assert.assertEquals(3, calculator.add("//;\n1;2")); Assert.assertEquals(3, calculator.add("1,2")); Assert.assertEquals(3, calculator.add("1\n2")); Assert.assertEquals(6, calculator.add("1,2\n3")); } @Test public void subtractNumbers() { StringCalculator calculator = new StringCalculator(); Assert.assertEquals(4, calculator.subtract("10,2,4")); Assert.assertEquals(0, calculator.subtract("")); Assert.assertEquals(-1, calculator.subtract("//;\n1;2")); Assert.assertEquals(-1, calculator.subtract("1,2")); Assert.assertEquals(-1, calculator.subtract("1\n2")); Assert.assertEquals(-4, calculator.subtract("1,2\n3")); } @Test public void multiplyNumbers() { StringCalculator calculator = new StringCalculator(); Assert.assertEquals(6, calculator.multiply("2,3")); Assert.assertEquals(0, calculator.multiply("")); Assert.assertEquals(2, calculator.multiply("//;\n1;2")); Assert.assertEquals(2, calculator.multiply("1,2")); Assert.assertEquals(2, calculator.multiply("1\n2")); Assert.assertEquals(6, calculator.multiply("1,2\n3")); } @Test public void testIsInteger() { assertFalse(StringCalculator.isInteger("test")); assertFalse(!StringCalculator.isInteger("2")); } }