From a1642e24af435e4b85ef8693c020427767e9a062 Mon Sep 17 00:00:00 2001 From: tjdjdjrdl123 Date: Mon, 2 Dec 2024 23:57:35 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=EC=89=BC=ED=91=9C,=20=EC=BD=9C?= =?UTF-8?q?=EB=A1=A0=EC=9C=BC=EB=A1=9C=20=EA=B5=AC=EB=B6=84=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=A0=80=EC=9E=A5=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/StringCalculator.kt | 14 ++++++++++++++ src/test/kotlin/StringCalculatorTest.kt | 14 ++++++++++++++ step1README.md | 13 +++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 src/main/kotlin/StringCalculator.kt create mode 100644 src/test/kotlin/StringCalculatorTest.kt create mode 100644 step1README.md diff --git a/src/main/kotlin/StringCalculator.kt b/src/main/kotlin/StringCalculator.kt new file mode 100644 index 0000000000..f799395d31 --- /dev/null +++ b/src/main/kotlin/StringCalculator.kt @@ -0,0 +1,14 @@ +data class StringCalculator(val totalNumber: Int) { + +constructor(inputString: String) : this( + splitString(inputString) + ) + + companion object { + private fun splitString(inputString: String): Int { + return inputString.split(Regex("[,:]")).map(String::toInt) + .sum() + } + } + +} diff --git a/src/test/kotlin/StringCalculatorTest.kt b/src/test/kotlin/StringCalculatorTest.kt new file mode 100644 index 0000000000..ef2e95abcb --- /dev/null +++ b/src/test/kotlin/StringCalculatorTest.kt @@ -0,0 +1,14 @@ +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.CsvSource + +class StringCalculatorTest { + + @ParameterizedTest + @DisplayName(value = "쉼표, 콜론을 구분자로 분리한다.") + @CsvSource(value = ["'1,2',3","'1:3',4"] ) + fun stringSplitTest(inputString : String, expacted : Int) { + assertThat(StringCalculator(inputString)).isEqualTo(StringCalculator(expacted)) + } +} diff --git a/step1README.md b/step1README.md new file mode 100644 index 0000000000..afd05e99d3 --- /dev/null +++ b/step1README.md @@ -0,0 +1,13 @@ +# 문자열 덧셈 계산기 + +기능 요구사항 +1. 쉼표, 콜론을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환한다.(""=>0, "1,2=>3, "1,2,3"=>6, "1,2:3"=>6) + 2. - [x] 쉼표, 콜론를 기본 구분자로 판단하여 분리하여 리스트에 저장.or 바로 더하기 +2. 앞의 기본 구분자외 커스텀 구분자 지정 가능. //와 \n 사이 위치문자를 커스텀 구분자로 사용한다. + 3. - [ ] //와 \n이 둘다 있을 경우 \\다음 문자를 구분자로 간주하고 분리 +3. 문자열 계산기에 숫자이외 값 or 음수 전달시 RuntimeException throw + 4. - [ ] 구분자로 분리하고 순회하면서 숫자 이외값 있을시 throw + + +구조 +문자열 계산기 클래스 From 785f6842b3c584b59691b7511231d37b8dce42ed Mon Sep 17 00:00:00 2001 From: tjdjdjrdl123 Date: Wed, 4 Dec 2024 23:57:27 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EA=B5=AC=EB=B6=84=EC=9E=90=20=EC=B2=98=EB=A6=AC=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/StringCalculator.kt | 25 +++++++++++++++++-------- src/test/kotlin/StringCalculatorTest.kt | 20 ++++++++++++++++---- step1README.md | 2 +- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/StringCalculator.kt b/src/main/kotlin/StringCalculator.kt index f799395d31..7826af907f 100644 --- a/src/main/kotlin/StringCalculator.kt +++ b/src/main/kotlin/StringCalculator.kt @@ -1,14 +1,23 @@ data class StringCalculator(val totalNumber: Int) { - -constructor(inputString: String) : this( - splitString(inputString) - ) + /*constructor(inputString: String){ + totalNumber = splitString(inputString) + }*/ companion object { - private fun splitString(inputString: String): Int { - return inputString.split(Regex("[,:]")).map(String::toInt) - .sum() + fun calculate(input: String): StringCalculator { + val result = Regex("//(.)\\n(.*)").find(input) + result?.let { + val customDelimiter = it.groupValues[1] + val customInput = it.groupValues[2] + return StringCalculator(splitString(customInput, customDelimiter)) + } + return StringCalculator(splitString(input, "[,:]")) } - } + private fun splitString( + inputString: String, + delimiter: String, + ) = inputString.split(Regex(delimiter)).map(String::toInt) + .sum() + } } diff --git a/src/test/kotlin/StringCalculatorTest.kt b/src/test/kotlin/StringCalculatorTest.kt index ef2e95abcb..adbf9af8e8 100644 --- a/src/test/kotlin/StringCalculatorTest.kt +++ b/src/test/kotlin/StringCalculatorTest.kt @@ -4,11 +4,23 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.CsvSource class StringCalculatorTest { - @ParameterizedTest @DisplayName(value = "쉼표, 콜론을 구분자로 분리한다.") - @CsvSource(value = ["'1,2',3","'1:3',4"] ) - fun stringSplitTest(inputString : String, expacted : Int) { - assertThat(StringCalculator(inputString)).isEqualTo(StringCalculator(expacted)) + @CsvSource(value = ["'1,2',3", "'1:3',4"]) + fun stringSplitTest( + inputString: String, + expacted: Int, + ) { + assertThat(StringCalculator.calculate(inputString)).isEqualTo(StringCalculator(expacted)) + } + + @ParameterizedTest + @DisplayName(value = "커스텀 구분자가 있으면 그 구분자로 분리한다.") + @CsvSource(value = ["'//;\n1;2',3", "'//_\n1_3',4"]) + fun customSplitTest( + inputString: String, + expacted: Int, + ) { + assertThat(StringCalculator.calculate(inputString)).isEqualTo(StringCalculator(expacted)) } } diff --git a/step1README.md b/step1README.md index afd05e99d3..8f2de13996 100644 --- a/step1README.md +++ b/step1README.md @@ -4,7 +4,7 @@ 1. 쉼표, 콜론을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환한다.(""=>0, "1,2=>3, "1,2,3"=>6, "1,2:3"=>6) 2. - [x] 쉼표, 콜론를 기본 구분자로 판단하여 분리하여 리스트에 저장.or 바로 더하기 2. 앞의 기본 구분자외 커스텀 구분자 지정 가능. //와 \n 사이 위치문자를 커스텀 구분자로 사용한다. - 3. - [ ] //와 \n이 둘다 있을 경우 \\다음 문자를 구분자로 간주하고 분리 + 3. - [x] //와 \n이 둘다 있을 경우 \\다음 문자를 구분자로 간주하고 분리 3. 문자열 계산기에 숫자이외 값 or 음수 전달시 RuntimeException throw 4. - [ ] 구분자로 분리하고 순회하면서 숫자 이외값 있을시 throw From 768a42009613b1f9f7e0ad3ade0e44217806fa4d Mon Sep 17 00:00:00 2001 From: tjdjdjrdl123 Date: Thu, 5 Dec 2024 00:25:02 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EA=B2=80=EC=A6=9D=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EA=B5=AC=EB=B6=84=EC=9E=90=EA=B0=80=20=EB=93=A4=EC=96=B4?= =?UTF-8?q?=EA=B0=94=EC=9D=84=EB=95=8C=20//=EC=99=80=20\n=EC=9D=80=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20=ED=95=84=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/StringCalculator.kt | 16 ++++++++++++---- src/test/kotlin/StringCalculatorTest.kt | 10 ++++++++++ step1README.md | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/StringCalculator.kt b/src/main/kotlin/StringCalculator.kt index 7826af907f..bf8bc9a7cb 100644 --- a/src/main/kotlin/StringCalculator.kt +++ b/src/main/kotlin/StringCalculator.kt @@ -5,13 +5,21 @@ data class StringCalculator(val totalNumber: Int) { companion object { fun calculate(input: String): StringCalculator { + var delimiter = "[,:]" + var text = input val result = Regex("//(.)\\n(.*)").find(input) result?.let { - val customDelimiter = it.groupValues[1] - val customInput = it.groupValues[2] - return StringCalculator(splitString(customInput, customDelimiter)) + delimiter = it.groupValues[1] + text = it.groupValues[2] + } + validate(text, delimiter) + return StringCalculator(splitString(input, delimiter)) + } + + private fun validate(input: String, delimiter: String) { + if (Regex("^(?!$delimiter$)(.*[^0-9].*)").containsMatchIn(input)) { + throw RuntimeException() } - return StringCalculator(splitString(input, "[,:]")) } private fun splitString( diff --git a/src/test/kotlin/StringCalculatorTest.kt b/src/test/kotlin/StringCalculatorTest.kt index adbf9af8e8..81f3fc391d 100644 --- a/src/test/kotlin/StringCalculatorTest.kt +++ b/src/test/kotlin/StringCalculatorTest.kt @@ -23,4 +23,14 @@ class StringCalculatorTest { ) { assertThat(StringCalculator.calculate(inputString)).isEqualTo(StringCalculator(expacted)) } + + @ParameterizedTest + @DisplayName(value = "음수 및 숫자 아닌값은 에러처리한다.") + @CsvSource(value = ["'-1:2',3", "'//_\n1_3',4"]) + fun SplitfailTest( + inputString: String, + expacted: Int, + ) { + assertThat(StringCalculator.calculate(inputString)).isEqualTo(StringCalculator(expacted)) + } } diff --git a/step1README.md b/step1README.md index 8f2de13996..38bacfbe16 100644 --- a/step1README.md +++ b/step1README.md @@ -6,7 +6,7 @@ 2. 앞의 기본 구분자외 커스텀 구분자 지정 가능. //와 \n 사이 위치문자를 커스텀 구분자로 사용한다. 3. - [x] //와 \n이 둘다 있을 경우 \\다음 문자를 구분자로 간주하고 분리 3. 문자열 계산기에 숫자이외 값 or 음수 전달시 RuntimeException throw - 4. - [ ] 구분자로 분리하고 순회하면서 숫자 이외값 있을시 throw + 4. - [ ] 구분자로 분리하고 순회하면서 숫자 이외값 있을시 throw. 이때 구분자랑 커스텀구분자는 제외 필요 구조 From 7fc1a48e39a8ae94d681f8e031263721080b15ee Mon Sep 17 00:00:00 2001 From: tjdjdjrdl123 Date: Sun, 8 Dec 2024 13:57:16 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=EC=88=AB=EC=9E=90=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B5=AC=EB=B6=84=EC=9E=90=20=EC=A0=9C=EC=99=B8=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EB=93=A4=20=EA=B2=80=EC=A6=9D=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/StringCalculator.kt | 4 ++-- src/test/kotlin/StringCalculatorTest.kt | 7 +++++-- step1README.md | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/StringCalculator.kt b/src/main/kotlin/StringCalculator.kt index bf8bc9a7cb..3506a2bba4 100644 --- a/src/main/kotlin/StringCalculator.kt +++ b/src/main/kotlin/StringCalculator.kt @@ -13,11 +13,11 @@ data class StringCalculator(val totalNumber: Int) { text = it.groupValues[2] } validate(text, delimiter) - return StringCalculator(splitString(input, delimiter)) + return StringCalculator(splitString(text, delimiter)) } private fun validate(input: String, delimiter: String) { - if (Regex("^(?!$delimiter$)(.*[^0-9].*)").containsMatchIn(input)) { + if (Regex("[^:,\\d\\n$delimiter//]").containsMatchIn(input)) { throw RuntimeException() } } diff --git a/src/test/kotlin/StringCalculatorTest.kt b/src/test/kotlin/StringCalculatorTest.kt index 81f3fc391d..87bce76079 100644 --- a/src/test/kotlin/StringCalculatorTest.kt +++ b/src/test/kotlin/StringCalculatorTest.kt @@ -1,4 +1,5 @@ import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatRuntimeException import org.junit.jupiter.api.DisplayName import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.CsvSource @@ -26,11 +27,13 @@ class StringCalculatorTest { @ParameterizedTest @DisplayName(value = "음수 및 숫자 아닌값은 에러처리한다.") - @CsvSource(value = ["'-1:2',3", "'//_\n1_3',4"]) + @CsvSource(value = ["'-1:2',3", "'//_\n1@3',4"]) fun SplitfailTest( inputString: String, expacted: Int, ) { - assertThat(StringCalculator.calculate(inputString)).isEqualTo(StringCalculator(expacted)) + assertThatRuntimeException().isThrownBy { + StringCalculator.calculate(inputString) + } } } diff --git a/step1README.md b/step1README.md index 38bacfbe16..6ca6680b34 100644 --- a/step1README.md +++ b/step1README.md @@ -6,7 +6,7 @@ 2. 앞의 기본 구분자외 커스텀 구분자 지정 가능. //와 \n 사이 위치문자를 커스텀 구분자로 사용한다. 3. - [x] //와 \n이 둘다 있을 경우 \\다음 문자를 구분자로 간주하고 분리 3. 문자열 계산기에 숫자이외 값 or 음수 전달시 RuntimeException throw - 4. - [ ] 구분자로 분리하고 순회하면서 숫자 이외값 있을시 throw. 이때 구분자랑 커스텀구분자는 제외 필요 + 4. - [x] 구분자로 분리하고 순회하면서 숫자 이외값 있을시 throw. 이때 구분자랑 커스텀구분자는 제외 필요 구조 From 0659d2378e9ce3c25978c52354a3178e1b58710e Mon Sep 17 00:00:00 2001 From: tjdjdjrdl123 Date: Sun, 8 Dec 2024 15:36:35 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/StringCalculator.kt | 31 -------------- src/main/kotlin/calculator/Main.kt | 10 +++++ .../kotlin/calculator/StringCalculator.kt | 41 +++++++++++++++++++ src/test/kotlin/StringCalculatorTest.kt | 22 +++++++++- 4 files changed, 71 insertions(+), 33 deletions(-) delete mode 100644 src/main/kotlin/StringCalculator.kt create mode 100644 src/main/kotlin/calculator/Main.kt create mode 100644 src/main/kotlin/calculator/StringCalculator.kt diff --git a/src/main/kotlin/StringCalculator.kt b/src/main/kotlin/StringCalculator.kt deleted file mode 100644 index 3506a2bba4..0000000000 --- a/src/main/kotlin/StringCalculator.kt +++ /dev/null @@ -1,31 +0,0 @@ -data class StringCalculator(val totalNumber: Int) { - /*constructor(inputString: String){ - totalNumber = splitString(inputString) - }*/ - - companion object { - fun calculate(input: String): StringCalculator { - var delimiter = "[,:]" - var text = input - val result = Regex("//(.)\\n(.*)").find(input) - result?.let { - delimiter = it.groupValues[1] - text = it.groupValues[2] - } - validate(text, delimiter) - return StringCalculator(splitString(text, delimiter)) - } - - private fun validate(input: String, delimiter: String) { - if (Regex("[^:,\\d\\n$delimiter//]").containsMatchIn(input)) { - throw RuntimeException() - } - } - - private fun splitString( - inputString: String, - delimiter: String, - ) = inputString.split(Regex(delimiter)).map(String::toInt) - .sum() - } -} diff --git a/src/main/kotlin/calculator/Main.kt b/src/main/kotlin/calculator/Main.kt new file mode 100644 index 0000000000..3016ae64da --- /dev/null +++ b/src/main/kotlin/calculator/Main.kt @@ -0,0 +1,10 @@ +package calculator + +import java.util.* + +fun main() { + println("계산식을 입력해주세요.") + val sc = Scanner(System.`in`) + val result = StringCalculator.calculate(sc.nextLine()) + println(result); +} diff --git a/src/main/kotlin/calculator/StringCalculator.kt b/src/main/kotlin/calculator/StringCalculator.kt new file mode 100644 index 0000000000..32e8e91948 --- /dev/null +++ b/src/main/kotlin/calculator/StringCalculator.kt @@ -0,0 +1,41 @@ +package calculator + +data class StringCalculator(val totalNumber: Int) { + + companion object { + fun calculate(input: String?): Int { + if (input.isNullOrBlank()) { + return 0 + } + + if (input.length==1 && input.all {it.isDigit()} ) { + return input.toInt() + } + + var delimiter = "[,:]" + var text = input + val result = Regex("//(.)\n(.*)").find(text) + result?.let { + delimiter = it.groupValues[1] + text = it.groupValues[2] + } + validate(text, delimiter) + return splitString(text, delimiter) + } + + private fun validate(input: String?, delimiter: String) { + if ( + Regex("[^\\d\n$delimiter//]").containsMatchIn(input.toString())) { + throw RuntimeException() + } + } + + private fun splitString( + inputString: String?, + delimiter: String, + ): Int { + return inputString?.split(Regex(delimiter))?.map(String::toInt) + ?.sum() ?: 0 + } + } +} diff --git a/src/test/kotlin/StringCalculatorTest.kt b/src/test/kotlin/StringCalculatorTest.kt index 87bce76079..07198e145e 100644 --- a/src/test/kotlin/StringCalculatorTest.kt +++ b/src/test/kotlin/StringCalculatorTest.kt @@ -1,8 +1,11 @@ +import calculator.StringCalculator import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatRuntimeException import org.junit.jupiter.api.DisplayName import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.CsvSource +import org.junit.jupiter.params.provider.NullAndEmptySource +import org.junit.jupiter.params.provider.ValueSource class StringCalculatorTest { @ParameterizedTest @@ -12,7 +15,7 @@ class StringCalculatorTest { inputString: String, expacted: Int, ) { - assertThat(StringCalculator.calculate(inputString)).isEqualTo(StringCalculator(expacted)) + assertThat(StringCalculator.calculate(inputString)).isEqualTo(expacted) } @ParameterizedTest @@ -22,7 +25,7 @@ class StringCalculatorTest { inputString: String, expacted: Int, ) { - assertThat(StringCalculator.calculate(inputString)).isEqualTo(StringCalculator(expacted)) + assertThat(StringCalculator.calculate(inputString)).isEqualTo(expacted) } @ParameterizedTest @@ -36,4 +39,19 @@ class StringCalculatorTest { StringCalculator.calculate(inputString) } } + + @DisplayName(value = "숫자 하나를 문자열로 입력할 경우 해당 숫자를 반환한다.") + @ParameterizedTest + @ValueSource(strings = ["1"]) + fun oneNumber(text: String) { + assertThat(StringCalculator.calculate(text)).isSameAs(Integer.parseInt(text)); + } + + + @DisplayName(value = "빈 문자열 또는 null 값을 입력할 경우 0을 반환해야 한다.") + @ParameterizedTest + @NullAndEmptySource + fun emptyOrNull(text: String?) { + assertThat(StringCalculator.calculate(text)).isZero(); + } } From 62fd5f3b034d01fd3cb26c48f939de2ad1c6b359 Mon Sep 17 00:00:00 2001 From: tjdjdjrdl123 Date: Tue, 10 Dec 2024 00:14:07 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/calculator/StringCalculator.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/calculator/StringCalculator.kt b/src/main/kotlin/calculator/StringCalculator.kt index 32e8e91948..ce1afe4d6b 100644 --- a/src/main/kotlin/calculator/StringCalculator.kt +++ b/src/main/kotlin/calculator/StringCalculator.kt @@ -8,19 +8,24 @@ data class StringCalculator(val totalNumber: Int) { return 0 } - if (input.length==1 && input.all {it.isDigit()} ) { + if (input.length == 1 && input.all { it.isDigit() }) { return input.toInt() } + val (delimiter, text) = parseDelimiterAndText(input) + validate(text, delimiter) + return splitString(text, delimiter) + } + + private fun parseDelimiterAndText(input: String?): Pair { var delimiter = "[,:]" var text = input - val result = Regex("//(.)\n(.*)").find(text) + val result = text?.let { Regex("//(.)\n(.*)").find(it) } result?.let { delimiter = it.groupValues[1] text = it.groupValues[2] } - validate(text, delimiter) - return splitString(text, delimiter) + return Pair(delimiter, text) } private fun validate(input: String?, delimiter: String) {