diff --git a/README.md b/README.md index bd90ef0247..b3010aa53b 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ -# java-calculator-precourse \ No newline at end of file +# 문자열 덧셈 계산기 + +## 구현할 기능 목록 + +- [x] 빈 문자열 또는 null 값을 입력할 경우 0을 반환한다. +- [x] 쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우, 구분자를 기준으로 분리한 각 숫자의 합을 반환한다. +- [x] 커스텀 구분자를 지정할 수 있다. + - 커스텀 구분자는 문자열 앞부분의 "//"와 "\n" 사이에 위치하는 문자를 사용한다. + - 예: `//;\n1;2;3` => 구분자: `;`, 결과: `6` +- [x] 음수를 입력할 경우 `IllegalArgumentException`을 발생시킨다. +- [x] 숫자가 아닌 값을 입력할 경우 `IllegalArgumentException`을 발생시킨다. +- [x] 사용자가 입력을 하고, 결과를 출력하는 UI를 구현한다. diff --git a/src/main/java/calculator/Application.java b/src/main/java/calculator/Application.java index 573580fb40..947e382567 100644 --- a/src/main/java/calculator/Application.java +++ b/src/main/java/calculator/Application.java @@ -1,7 +1,19 @@ package calculator; +import camp.nextstep.edu.missionutils.Console; + public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + StringCalculator calculator = new StringCalculator(); + + System.out.println("덧셈할 문자열을 입력해 주세요."); + String input = Console.readLine(); + + try { + int result = calculator.add(input); + System.out.println("결과 : " + result); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } } } diff --git a/src/main/java/calculator/StringCalculator.java b/src/main/java/calculator/StringCalculator.java new file mode 100644 index 0000000000..be845deb64 --- /dev/null +++ b/src/main/java/calculator/StringCalculator.java @@ -0,0 +1,53 @@ +package calculator; + +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.IntStream; + +public class StringCalculator { + + private static final Pattern CUSTOM_DELIMITER_PATTERN = Pattern.compile("//(.)\n(.*)"); + private static final String DEFAULT_DELIMITERS = "[,:]"; + + public int add(String text) { + if (text == null || text.isBlank()) { + return 0; + } + + String[] numbers = split(text); + IntStream stream = toIntStream(numbers); + + return sum(stream); + } + + private String[] split(String text) { + Matcher matcher = CUSTOM_DELIMITER_PATTERN.matcher(text); + if (matcher.find()) { + String customDelimiter = matcher.group(1); + String numbersText = matcher.group(2); + return numbersText.split(Pattern.quote(customDelimiter)); + } + return text.split(DEFAULT_DELIMITERS); + } + + private IntStream toIntStream(String[] numbers) { + try { + return Arrays.stream(numbers) + .mapToInt(Integer::parseInt); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("숫자가 아닌 값이 포함되어 있습니다."); + } + } + + private int sum(IntStream stream) { + int[] numbers = stream.toArray(); + + long negativeCount = Arrays.stream(numbers).filter(n -> n < 0).count(); + if (negativeCount > 0) { + throw new IllegalArgumentException("음수는 입력할 수 없습니다."); + } + + return Arrays.stream(numbers).sum(); + } +}