Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions soyangel/StringCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import java.util.regex.Pattern;

public class StringCalculator
{

private static final String NEGATIVES_MESSAGE = "Negatives not allowed";
private static final String NUMBER_SEPARATOR = ",|\n";
private static final String PREFIX_CUSTOM_DELIMITER = "//";

public static int calculate(String numbers) throws Exception
{
int[] operands = extractNumbers(numbers);
return addNumbers(operands);
}

private static int[] extractNumbers(String numbers)
{
String[] operands = splitArray(numbers);
return stringArrayToIntArray(operands);
}

private static String[] splitArray(String numbers)
{
if (numbers.equals(""))
return new String[0];

String delimiter = getDelimiter(numbers);
numbers = removeDelimiterDefinition(numbers);
return numbers.split(delimiter);
}

private static String removeDelimiterDefinition(String numbers)
{
if (numbers.startsWith(PREFIX_CUSTOM_DELIMITER))
return numbers.replaceFirst(PREFIX_CUSTOM_DELIMITER + ".\n", "");
else
return numbers;
}

private static String getDelimiter(String numbers)
{
if (numbers.startsWith(PREFIX_CUSTOM_DELIMITER))
return extractDeclaredDelimiter(numbers);
else
return NUMBER_SEPARATOR;
}

private static String extractDeclaredDelimiter(String numbers)
{
String delimiter = numbers.split("//|\n")[1];
return Pattern.quote(delimiter);
}

private static int addNumbers(int[] numbers) throws Exception
{
int sum = 0;
String negativeNumbers = "";
for (int number : numbers)
{
if (number < 0)
negativeNumbers += " " + number;
else
sum += number;
}

if (negativeNumbers.isEmpty())
return sum;
else
throw new Exception(NEGATIVES_MESSAGE + negativeNumbers);
}

private static int[] stringArrayToIntArray(String[] operands)
{
int[] result = new int[operands.length];

for (int i = 0; i < operands.length; i++)
{
result[i] = Integer.parseInt(operands[i]);
}

return result;
}

}
90 changes: 90 additions & 0 deletions soyangel/StringCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import static org.junit.Assert.*;

import org.junit.Test;

public class StringCalculatorTest
{
@Test
public void canCalculate0Numbers() throws Exception
{
assertEquals(0, StringCalculator.calculate(""));
}

@Test
public void canCalculate1Number() throws Exception
{
assertEquals(0, StringCalculator.calculate("0"));
assertEquals(1, StringCalculator.calculate("1"));
}

@Test
public void canCalculate2Numbers() throws Exception
{
assertEquals(1, StringCalculator.calculate("0,1"));
assertEquals(3, StringCalculator.calculate("1,2"));
}

@Test
public void canCalculateUnknownAmountOfNumbers() throws Exception
{
assertEquals(55, StringCalculator.calculate("0,1,2,3,4,5,6,7,8,9,10"));
}

@Test
public void canUseNewlineAsSeparator() throws Exception
{
assertEquals(1, StringCalculator.calculate("0\n1"));
assertEquals(3, StringCalculator.calculate("0\n1,2"));
}

@Test
public void canSupportDefinableDelimiters() throws Exception
{
assertEquals(10, StringCalculator.calculate("//;\n1;2;4;3"));
assertEquals(10, StringCalculator.calculate("//.\n1.2.4.3"));
assertEquals(21, StringCalculator.calculate("//*\n5*6*10"));
}

@Test
public void mustThrowExceptionOnNegatives() throws Exception
{
try
{
StringCalculator.calculate("0\n-1");
fail("Exception expected but not thrown");
}
catch (Exception e)
{
assertEquals("Negatives not allowed -1", e.getMessage());
}
}

@Test
public void mustThrowExceptionOnNegativesWithPrefix() throws Exception
{
try
{
StringCalculator.calculate("//*\n5*-6*10");
fail("Exception expected but not thrown");
}
catch (Exception e)
{
assertEquals("Negatives not allowed -6", e.getMessage());
}
}

@Test
public void mustThrowExceptionOnSeveralNegativesWithPrefix() throws Exception
{
try
{
StringCalculator.calculate("//*\n5*-6*-10*-2");
fail("Exception expected but not thrown");
}
catch (Exception e)
{
assertEquals("Negatives not allowed -6 -10 -2", e.getMessage());
}
}

}