Skip to content

2단계 - 문자열 계산기 #1178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: sksskaw
Choose a base branch
from
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
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
# kotlin-racingcar
# kotlin-racingcar

### 문자열 계산기 사용법

각 숫자와 연산자는 " " 공백문자로 구분한다.

숫자는 정수로만 작성해야한다. 실수가 포함 될 경우 예외발생

나눗셈("/")의 경우 몫으로 처리한다._ ex) "10 / 3" -> 3
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
testImplementation("org.junit.jupiter", "junit-jupiter", "5.8.2")
testImplementation("org.assertj", "assertj-core", "3.22.0")
testImplementation("io.kotest", "kotest-runner-junit5", "5.2.3")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.2")
}

tasks {
Expand Down
Empty file removed src/main/kotlin/.gitkeep
Empty file.
27 changes: 27 additions & 0 deletions src/main/kotlin/stringCalculator/Operation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package stringCalculator

class Operation {
companion object {
fun operation(x: String, y: String, o: String): Int {
val operator = Operator.values().find { it.operator == o }
?: throw IllegalArgumentException("+ - * / 를 제외한 다른 연산자가 포함되어 있습니다.")

return operator.result(x, y)
}
}
}

enum class Operator(val operator: String, val result: (String, String) -> Int) {
PLUS(
"+", { s1, s2 -> Integer.valueOf(s1) + Integer.valueOf(s2) },
),
MINUS(
"-", { s1, s2 -> Integer.valueOf(s1) - Integer.valueOf(s2) },
),
MULTIPLY(
"*", { s1, s2 -> Integer.valueOf(s1) * Integer.valueOf(s2) },
),
DIVISION(
"/", { s1, s2 -> Integer.valueOf(s1) / Integer.valueOf(s2) },
),
}
12 changes: 12 additions & 0 deletions src/main/kotlin/stringCalculator/StringCalculator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package stringCalculator

class StringCalculator {
private var stringCalculatorScanner = StringCalculatorScanner()

fun calculate(input: String?): Int {
if (input.isNullOrEmpty())
throw IllegalArgumentException("문자열을 확인해 주세요")

return stringCalculatorScanner.scan(input.split(" "))
}
}
16 changes: 16 additions & 0 deletions src/main/kotlin/stringCalculator/StringCalculatorScanner.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package stringCalculator

class StringCalculatorScanner {
fun scan(input: List<String>): Int {
val stringOperator = StringOperator()

input.forEach { str ->
when (StringParser.parseString(str)) {
StringType.NUMBER -> stringOperator.numberProcess(str)
StringType.OPERATOR -> stringOperator.operatorProcess(str)
}
}

return stringOperator.getResult()
}
}
37 changes: 37 additions & 0 deletions src/main/kotlin/stringCalculator/StringOperator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package stringCalculator

class StringOperator(
private var firstOperand: String? = null,
private var secondOperand: String? = null,
private var operator: String? = null,
private var operateResult: Int = 0
) {
private fun operate(): Int {
if (firstOperand != null && secondOperand != null && operator != null) {
operateResult = Operation.operation(firstOperand!!, secondOperand!!, operator!!)
firstOperand = operateResult.toString()
secondOperand = null
operator = null
}

return operateResult
}

fun numberProcess(str: String) {
if (firstOperand == null)
firstOperand = str

if (operator != null && secondOperand == null)
secondOperand = str

operate()
}

fun operatorProcess(str: String) {
operator = str
}

fun getResult(): Int {
return operateResult
}
}
24 changes: 24 additions & 0 deletions src/main/kotlin/stringCalculator/StringParser.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package stringCalculator

import java.lang.NumberFormatException

class StringParser {
companion object {
fun parseString(str: String): StringType {
if (Operator.values().any { it.operator == str })
return StringType.OPERATOR

try {
str.toInt()
return StringType.NUMBER
} catch (e: NumberFormatException) {
throw NumberFormatException("문자열을 확인해 주세요")
}
}
}
}

enum class StringType {
NUMBER,
OPERATOR,
}
Empty file removed src/test/kotlin/.gitkeep
Empty file.
68 changes: 68 additions & 0 deletions src/test/kotlin/stringCalculatorTest/StringCalculatorTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package stringCalculatorTest

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import stringCalculator.StringCalculator

class StringCalculatorTest {
@ParameterizedTest
@CsvSource(
"5 + 6 + 9 + 10, 30",
"15 + 100 + 1500 + 1, 1616"
)
fun `덧셈`(input: String, expected: Int) {
val calculator = StringCalculator()
val result = calculator.calculate(input)

Assertions.assertEquals(expected, result)
}

@ParameterizedTest
@CsvSource(
"10 - 5 - 3 - 1, 1",
"100 - 10 - 20 - 5, 65"
)
fun `뺄셈`(input: String, expected: Int) {
val calculator = StringCalculator()
val result = calculator.calculate(input)

Assertions.assertEquals(expected, result)
}

@ParameterizedTest
@CsvSource(
"5 * 5 * 5, 125",
"100 * 5 * 2, 1000"
)
fun `곱셈`(input: String, expected: Int) {
val calculator = StringCalculator()
val result = calculator.calculate(input)

Assertions.assertEquals(expected, result)
}

@ParameterizedTest
@CsvSource(
"50 / 5 / 2, 5",
"100 / 5 / 3, 6"
)
fun `나눗셈`(input: String, expected: Int) {
val calculator = StringCalculator()
val result = calculator.calculate(input)

Assertions.assertEquals(expected, result)
}

@ParameterizedTest
@CsvSource(
"50 + 9 * 5 * 3 - 111 / 2, 387",
"33 + 1 * 2 * 2 - 1111 / 2, -487"
)
fun `복합 계산`(input: String, expected: Int) {
val calculator = StringCalculator()
val result = calculator.calculate(input)

Assertions.assertEquals(expected, result)
}
}
32 changes: 32 additions & 0 deletions src/test/kotlin/stringCalculatorTest/StringOperatorTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package stringCalculatorTest

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import stringCalculator.StringOperator

class StringOperatorTest {
@Test
fun `연산자, 모든 피연산자가 모두 null이 아닌 경우에만 연산 수행`() {
val stringOperator = StringOperator()
stringOperator.numberProcess("3")
stringOperator.operatorProcess("+")
stringOperator.numberProcess("7")
assertThat(stringOperator.getResult()).isEqualTo(10)
}

@Test
fun `연산자가 null일 경우`() {
val stringOperator = StringOperator()
stringOperator.numberProcess("3")
stringOperator.numberProcess("7")
assertThat(stringOperator.getResult()).isEqualTo(0)
}

@Test
fun `피연산자 하나가 null일 경우`() {
val stringOperator = StringOperator()
stringOperator.numberProcess("3")
stringOperator.operatorProcess("+")
assertThat(stringOperator.getResult()).isEqualTo(0)
}
}
28 changes: 28 additions & 0 deletions src/test/kotlin/stringCalculatorTest/StringParserTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package stringCalculatorTest

import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import stringCalculator.StringParser
import stringCalculator.StringType
import java.lang.NumberFormatException

class StringParserTest {
@ParameterizedTest
@CsvSource(
"10, NUMBER",
"*, OPERATOR"
)
fun parseStringTest(input: String, expected: StringType) {
val result = StringParser.parseString(input)
Assertions.assertEquals(expected, result)
}

@Test
fun numberFormatExceptionTest() {
Assertions.assertThrows(NumberFormatException::class.java) {
StringParser.parseString("45.11")
}
}
}