diff --git a/README.md b/README.md index 8fe711203..b64c61842 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ +## 1. 문자열 덧셈 계산기 +### 요구사항 +- : 또는 ,를 구분자로 한다. `Separator#separate` +- 커스텀 구분자를 지정할 수 있다. + 1. //와 \n 사이에 입력한 값이 커스텀 구분자가 된다. -> //로 시작하면 \n만날 때까지 값을 구분자에 저장한다. `Separator#getCustomSeparator` + 2. //&\n1&2&3 -> 1+2+3 = 6 -> (커스텀)구분자 이용해서 덧셈 진행 -> `Calculator#plus` +- 숫자이외의 값 혹은 음수를 입력할 경우 RuntimeException을 던진다. -> `Calculator#isCorrectNumeric` + +<추가 제한 사항> +- 커스텀 지정한 경우 입력 시, 지정 커스텀으로만 구성한다. +- 커스텀은 한글자이어야 한다. + +--- + ## [NEXTSTEP 플레이그라운드의 미션 진행 과정](https://github.com/next-step/nextstep-docs/blob/master/playground/README.md) --- diff --git a/src/main/java/calculator/Calculator.java b/src/main/java/calculator/Calculator.java new file mode 100644 index 000000000..f2568ac67 --- /dev/null +++ b/src/main/java/calculator/Calculator.java @@ -0,0 +1,51 @@ +package calculator; + +import java.util.ArrayList; +import java.util.List; + +public class Calculator { + private static final String MINUS_REGEX = "-"; + + public int plus(String[] input) { + int sum = 0; + checkCorrectNumeric(input); + + List nums = changeToIntNums(input); + for(int num : nums) { + sum += num; + } + return sum; + } + // 1. 숫자 이외의 값 있는지 검증 2. 음수인지 검증 + private List changeToIntNums(String[] input) { + List nums = new ArrayList<>(); + for (String i : input) { + nums.add(Integer.parseInt(i)); + } + return nums; + } + + private boolean isNullOrEmpty(String str) { + return str == null || "".equals(str); + } + + /** + * 1. 정규식 + * 2. Double.parseDouble()을 통해 catch문 시 return false + * TODO two depth... + */ + private void checkCorrectNumeric(String[] str) { + for (int i = 0; i < str.length; i++) { + if(isNullOrEmpty(str[i])) { + str[i] = "0"; + continue; + } + if(str[i].matches("[^0-9]")) { + throw new RuntimeException("숫자 외의 값은 불가능합니다."); + } + if (str[i].startsWith(MINUS_REGEX)) { + throw new RuntimeException("0 이상의 정수만 가능합니다."); + } + } + } +} diff --git a/src/main/java/calculator/Separator.java b/src/main/java/calculator/Separator.java new file mode 100644 index 000000000..f499efb48 --- /dev/null +++ b/src/main/java/calculator/Separator.java @@ -0,0 +1,41 @@ +package calculator; + +/** + * 새로 알게된 점 + * 1. 개행문자(\n)의 \는 2개 적어주어야 한다. ex) "\\n" + * 2. 몇몇 문자(+,^,*)는 코드 상 의미를 가지기 때문에 "//"를 붙여줘야 한다. + */ +public class Separator { + private static final String CUSTOM_REGEX_PREFIX = "//"; + private static final String CUSTOM_REGEX_SUFFIX = "\n"; + public String[] separate(String input) { + String regex = ",|:"; + if (input.startsWith(CUSTOM_REGEX_PREFIX)) { + regex = getCustomSeparator(input); + input = deleteRegex(input, regex); + } + if (hasRegexMeaning(regex)) { + regex = "\\"+ regex; + } + return input.split(regex); + } + // 의미있는 구분자를 사용하는가? (+, ^, *) + private boolean hasRegexMeaning(String regex) { + return "+^*".contains(regex); + } + + // "//*\n1*2*3" + private String deleteRegex(String input, String regex) { + int total = CUSTOM_REGEX_PREFIX.length() + CUSTOM_REGEX_SUFFIX.length() + regex.length(); + return input.substring(total); + } + private String getCustomSeparator(String inputWithCustomRegex) { + for (int i=2; i< inputWithCustomRegex.length()-1; i++) { + String tmp = inputWithCustomRegex.substring(i, i + 1); // substring(a,b) : a부터 b 위치 포함 값까지 + if (CUSTOM_REGEX_SUFFIX.equals(tmp)) { + return inputWithCustomRegex.substring(2, i); + } + } + throw new RuntimeException("알맞은 구분자가 아닙니다."); + } +} diff --git a/src/test/java/calculator/CalculatorTest.java b/src/test/java/calculator/CalculatorTest.java new file mode 100644 index 000000000..f544b8c42 --- /dev/null +++ b/src/test/java/calculator/CalculatorTest.java @@ -0,0 +1,36 @@ +package calculator; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CalculatorTest { + + @Test + @DisplayName("실패 - 숫자 이외의 값 혹은 음수를 던진다.") + void plusFailedTest() { + String[] inputWithMinus = new String[]{"1", "-1", "0"}; + String[] inputWithAlphabet = new String[]{"1", "-", "a"}; + Calculator cal = new Calculator(); + Assertions.assertThrows(RuntimeException.class, () -> cal.plus(inputWithMinus)); + Assertions.assertThrows(RuntimeException.class, () -> cal.plus(inputWithAlphabet)); + } + + @Test + @DisplayName("빈 문자를 던진다.") + void nullTest() { + String[] inputWithNull = new String[]{null}; + Calculator cal = new Calculator(); + assertThat(cal.plus(inputWithNull)).isEqualTo(0); + } + + @Test + @DisplayName("주어진 배열 숫자로 덧셈한다.") + void plusTest() { + String[] input = new String[]{"1","2","3"}; + Calculator cal = new Calculator(); + assertThat(cal.plus(input)).isEqualTo(1+2+3); + } +} diff --git a/src/test/java/calculator/SeparatorTest.java b/src/test/java/calculator/SeparatorTest.java new file mode 100644 index 000000000..cdcdd946d --- /dev/null +++ b/src/test/java/calculator/SeparatorTest.java @@ -0,0 +1,42 @@ +package calculator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SeparatorTest { + + @Test + @DisplayName("기본 구분자(,|:)로 구분한다.") + void basicTwoSeparatorsTest() { + Separator separator = new Separator(); + String input = "1,2:3"; + assertThat(separator.separate(input)).isEqualTo(new String[]{"1","2","3"}); + } + @Test + @DisplayName("기본 구분자(,)로 구분한다.") + void basicOneSeparatorTest() { + Separator separator = new Separator(); + String input = "1,2"; + assertThat(separator.separate(input)).isEqualTo(new String[]{"1","2"}); + } + + @Test + @DisplayName("커스텀 구분자로 구분한다.") + void customSeparatorTest() { + Separator separator = new Separator(); + String inputWithStarSplit = "//*\n1*2*3"; + String inputWithCollonSplit = "//;\n1;2;3"; + assertThat(separator.separate(inputWithStarSplit)).isEqualTo(new String[]{"1","2","3"}); + assertThat(separator.separate(inputWithCollonSplit)).isEqualTo(new String[]{"1","2","3"}); + } + + @Test + @DisplayName("숫자 한개만 입력한다.") + void inputOnlyOneNumberTest() { + Separator separator = new Separator(); + String input = "1"; + assertThat(separator.separate(input)).isEqualTo(new String[]{"1"}); + } +}