From 22f9d93880efb5f50f7db8aea76903c459500ab0 Mon Sep 17 00:00:00 2001 From: rbgusdlza Date: Mon, 10 Jun 2024 02:32:29 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=ED=95=99=EC=8A=B5=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/string/SubstringTest.java | 10 ++++++ src/test/java/study/SetTest.java | 43 +++++++++++++++++++++++++ src/test/java/study/StringTest.java | 26 +++++++++++++-- 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/main/java/string/SubstringTest.java create mode 100644 src/test/java/study/SetTest.java diff --git a/src/main/java/string/SubstringTest.java b/src/main/java/string/SubstringTest.java new file mode 100644 index 000000000..95b536040 --- /dev/null +++ b/src/main/java/string/SubstringTest.java @@ -0,0 +1,10 @@ +package string; + +public class SubstringTest { + + public static void main(String[] args) { + String str = "(1,2)"; + String substring = str.substring(1, 4); + System.out.println("substring = " + substring); + } +} diff --git a/src/test/java/study/SetTest.java b/src/test/java/study/SetTest.java new file mode 100644 index 000000000..0821cb21a --- /dev/null +++ b/src/test/java/study/SetTest.java @@ -0,0 +1,43 @@ +package study; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.HashSet; +import java.util.Set; + +import static org.assertj.core.api.Assertions.*; + +class SetTest { + + private Set numbers; + + @BeforeEach + void setUp() { + numbers = new HashSet<>(); + numbers.add(1); + numbers.add(1); + numbers.add(2); + numbers.add(3); + } + + @Test + void size() { + assertThat(numbers.size()).isEqualTo(3); + } + + @ParameterizedTest + @ValueSource(ints = {1, 2, 3}) + void contains(int value) { + assertThat(numbers.contains(value)).isTrue(); + } + + @ParameterizedTest + @CsvSource(value = {"1,true", "4,false", "5,false"}) + void containsUsingCsv(int value, boolean expected) { + assertThat(numbers.contains(value)).isEqualTo(expected); + } +} diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java index 43e47d90b..538536e79 100644 --- a/src/test/java/study/StringTest.java +++ b/src/test/java/study/StringTest.java @@ -1,13 +1,35 @@ package study; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; + +class StringTest { -public class StringTest { @Test void replace() { String actual = "abc".replace("b", "d"); assertThat(actual).isEqualTo("adc"); } + + @Test + void split() { + String[] actual = "1,2".split(","); + assertThat(actual).contains("1", "2"); + } + + @Test + void split2() { + String[] actual = "1".split(","); + assertThat(actual).containsExactly("1"); + } + + @DisplayName("문자열 범위 밖의 인덱스로 문자열을 참조할 때 에러가 발생한다.") + @Test + void charAt() { + String actual = "abc"; + assertThatThrownBy(() -> actual.charAt(4)) + .isInstanceOf(StringIndexOutOfBoundsException.class); + } } From 2393518fccb5e9624b8415cf5b1b9ba2bac2a901 Mon Sep 17 00:00:00 2001 From: rbgusdlza Date: Sat, 10 Aug 2024 03:08:51 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=EA=B8=B0=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/calculator/StringCalculator.java | 40 +++++++++++ .../java/calculator/StringCalculatorTest.java | 71 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 src/main/java/calculator/StringCalculator.java create mode 100644 src/test/java/calculator/StringCalculatorTest.java diff --git a/src/main/java/calculator/StringCalculator.java b/src/main/java/calculator/StringCalculator.java new file mode 100644 index 000000000..59dbdb715 --- /dev/null +++ b/src/main/java/calculator/StringCalculator.java @@ -0,0 +1,40 @@ +package calculator; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 요구사항 + * 1. 빈 문자열 또는 null 값을 입력할 경우 0을 반환해야 한다. + * 2. 숫자 하나를 문자열로 입력할 경우 해당 숫자를 반환한다. + * 3. 숫자 두개를 쉼표(,) 구분자로 입력할 경우 두 숫자의 합을 반환한다. + * 4. 구분자를 쉼표(,) 이외에 콜론(:)을 사용할 수 있다. + * 5. "//"와 "\n" 문자 사이에 커스텀 구분자를 지정할 수 있다. + * 6. 음수를 전달하는 경우 RuntimeException 예외 처리를 한다. + */ +public class StringCalculator { + + public int add(String text) { + if (text == null || text.isEmpty()) return 0; + Matcher m = Pattern.compile("//(.)\n(.*)").matcher(text); + if (m.find()) { + String customDelimiter = m.group(1); + String[] tokens = m.group(2).split(customDelimiter); + return addNumbersSplitBy(tokens); + } + String[] tokens = text.split(",|:"); + return addNumbersSplitBy(tokens); + } + + private int addNumbersSplitBy(String[] tokens) { + int sum = 0; + for (String token : tokens) { + int number = Integer.parseInt(token); + if (number < 0) { + throw new RuntimeException(); + } + sum += number; + } + return sum; + } +} diff --git a/src/test/java/calculator/StringCalculatorTest.java b/src/test/java/calculator/StringCalculatorTest.java new file mode 100644 index 000000000..b45c9efa2 --- /dev/null +++ b/src/test/java/calculator/StringCalculatorTest.java @@ -0,0 +1,71 @@ +package calculator; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class StringCalculatorTest { + + private final StringCalculator stringCalculator = new StringCalculator(); + + @DisplayName("빈 문자열 또는 null 값을 입력할 경우 0을 반환해야 한다.") + @Test + void add1() { + //given //when + int result1 = stringCalculator.add(""); + int result2 = stringCalculator.add(null); + + //then + assertThat(result1).isZero(); + assertThat(result2).isZero(); + } + + @DisplayName("숫자 하나를 문자열로 입력할 경우 해당 숫자를 반환한다.") + @Test + void add2() { + //given //when + int result = stringCalculator.add("1"); + + //then + assertThat(result).isEqualTo(1); + } + + @DisplayName("숫자 두개를 쉼표(,) 구분자로 입력할 경우 두 숫자의 합을 반환한다.") + @Test + void add3() { + //given //when + int result = stringCalculator.add("1,3"); + + //then + assertThat(result).isEqualTo(4); + } + + @DisplayName("구분자를 쉼표(,) 이외에 콜론(:)을 사용할 수 있다.") + @Test + void add4() { + //given //when + int result = stringCalculator.add("1,2:3"); + + //then + assertThat(result).isEqualTo(6); + } + + @DisplayName("지정 문자 사이에 커스텀 구분자를 지정할 수 있다.") + @Test + void add5() { + //given //when + int result = stringCalculator.add("//;\n1;2;3"); + + //then + assertThat(result).isEqualTo(6); + } + + @DisplayName("음수를 전달하는 경우 RuntimeException 예외 처리를 한다.") + @Test + void add6() { + //given //when //then + assertThatThrownBy(() -> stringCalculator.add("1,-2")) + .isInstanceOf(RuntimeException.class); + } +} \ No newline at end of file From 237b015acbddb0e34d2efacb9047e6f531763445 Mon Sep 17 00:00:00 2001 From: rbgusdlza Date: Sat, 10 Aug 2024 03:27:34 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=EA=B8=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/calculator/StringCalculator.java | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/main/java/calculator/StringCalculator.java b/src/main/java/calculator/StringCalculator.java index 59dbdb715..3c07fada2 100644 --- a/src/main/java/calculator/StringCalculator.java +++ b/src/main/java/calculator/StringCalculator.java @@ -15,26 +15,45 @@ public class StringCalculator { public int add(String text) { - if (text == null || text.isEmpty()) return 0; + if (isBlank(text)) { + return 0; + } + return sum(toPositives(split(text))); + } + + private boolean isBlank(String text) { + return text == null || text.isEmpty(); + } + + private String[] split(String text) { Matcher m = Pattern.compile("//(.)\n(.*)").matcher(text); if (m.find()) { String customDelimiter = m.group(1); - String[] tokens = m.group(2).split(customDelimiter); - return addNumbersSplitBy(tokens); + return m.group(2).split(customDelimiter); } - String[] tokens = text.split(",|:"); - return addNumbersSplitBy(tokens); + return text.split(",|:"); } - private int addNumbersSplitBy(String[] tokens) { + private int[] toPositives(String[] values) { + int[] numbers = new int[values.length]; + for (int i = 0; i < values.length; i++) { + numbers[i] = Integer.parseInt(values[i]); + } + return numbers; + } + + private int sum(int[] numbers) { int sum = 0; - for (String token : tokens) { - int number = Integer.parseInt(token); - if (number < 0) { - throw new RuntimeException(); - } + for (int number : numbers) { + checkIfNumberIsNegative(number); sum += number; } return sum; } + + private static void checkIfNumberIsNegative(int number) { + if (number < 0) { + throw new RuntimeException(); + } + } }