Last active
June 7, 2022 01:33
-
-
Save dotNetTree/9035dda235cb171025bdbbcc7c9e114f to your computer and use it in GitHub Desktop.
Code Spitz 90 - 코틀린 언어편 (1) 과제
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val trim = """[^.\d-+*/()]""".toRegex() | |
fun trim(v: String): String = v.replace(trim, "") | |
fun repMMtoP(v: String) = v.replace("--", "+") | |
fun repMtoPM(v: String) = v.replace("-", "+-") | |
val groupMD = """((?:\+|\+-)?[.\d]+)([*/])((?:\+|\+-)?[.\d]+)""".toRegex() | |
tailrec fun removeMultiDiv(v: String): String = groupMD.find(v).let { | |
if (it != null) { | |
val (target, left, op, right) = it.groupValues | |
val leftValue = left.replace("+", "").toDouble() | |
val rightValue = right.replace("+", "").toDouble() | |
val result = when (op) { | |
"*" -> leftValue * rightValue | |
"/" -> leftValue / rightValue | |
else -> throw Throwable("invalid operator $op") | |
} | |
removeMultiDiv(v.replace(target, "+$result")) | |
} else v | |
} | |
fun calcWithBracket(v: String): Double { | |
return v | |
.let { v.drop(1).dropLast(1) } | |
.let { trim(it) } | |
.let { repMMtoP(it) } | |
.let { repMtoPM(it) } | |
.let { removeMultiDiv(it) } | |
.split("""(\++)""".toRegex()) | |
.fold(0.0) { accu, curr -> | |
if (curr.isBlank()) { accu } else accu + curr.toDouble() | |
} | |
} | |
tailrec fun removeBracket(v: String): String { | |
return """\([.\d+\-*/]+\)""".toRegex().findAll(v).let { | |
if (it.count() == 0) v | |
else removeBracket( | |
it.fold(v) { acc, cur -> | |
val target = cur.value | |
val ret = calcWithBracket(target) | |
acc.replace(target, "$ret") | |
} | |
) | |
} | |
} | |
fun calc(v: String): Double = removeBracket("(${trim(v)})").toDouble() | |
fun main(args: Array<String>) { | |
val exps: Array<String> = arrayOf( | |
"16 / 2 / 2 / 2", | |
"-2 -3 + 0.4", | |
"-2 * (-3 + 0.4) / -0.2", | |
"-2 * (-3 + 0.4) / -0.2 + .55", | |
"-2 - (-3 + -8 * (7 + 3)) + (0.4 / -0.2)", | |
) | |
for (exp in exps) { | |
println("$exp = ${calc(exp)}") | |
} | |
} |
@hannut91 코드 리뷰 감사합니다. 리뷰 해주신 내용 반영하였습니다.
그런데, 한가지 질문이 있습니다.
그리고 하나 더, 변수를 선언한 곳과 사용하는 곳은 거리가 가까울수록 좋습니다. 특히 상수가 아닌 변수는 선언한 곳과 사용하는 곳이 멀어질수록 그 사이에 변수에 무슨 짓을 할지 모르기 때문에, 그 사이를 모두 의심의 눈초리로 코드를 봐야 합니다.
class가 등장하게 되면 프로퍼티와 선언(변수)와 사용처인 메소드가 물리적으로 매우 떨어지게 되는데요. 이 경우에도 같은 룰을 적용해야 하는건가요?
그리고 guard pattern은 sequence로 부터 Interactor 객체를 얻어내는 것보단 count method를 활용하는게 더 좋을 것습니다.
class가 등장하게 되면 프로퍼티와 선언(변수)와 사용처인 메소드가 물리적으로 매우 떨어지게 되는데요. 이 경우에도 같은 룰을 적용해야 하는건가요?
가능한 가까우면 좋은데, 무조건 그런 것은 아닙니다! 클래스가 등장하면 변수를 위에 놓고 메서드를 쓰니 꼭 그렇게 되지는 않겠죠 ㅎㅎ 변수를 사용할 때도 때로는 변수를 모아놓는 것이 좋을 때가 있는 것 같아요.
그리고 guard pattern은 sequence로 부터 Interactor 객체를 얻어내는 것보단 count method를 활용하는게 더 좋을 것습니다.
count 메서드가 있었군요 감사합니다!
@hannut91 감사합니다.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
'16 / 2 / 2 / 2'의 결과가 2가 나와야 하는데 8이 나오고 있네요. 그 이유는 계산할 때 지금 아래와 같이 계산이 되고 있어요.
나누기의 경우 앞에서부터 차례대로 계산이 되어야 할 것 같습니다