본문 바로가기
  • 개발하는 곰돌이
Algorithm/BOJ

[Kotlin] 백준 23629 : 이 얼마나 끔찍하고 무시무시한 수식이니

by 개발하는 곰돌이 2023. 1. 14.

문제 링크

 

23629번: 이 얼마나 끔찍하고 무시무시한 수식이니

영문 대문자 및 +,-,x,/,=로 이루어진 문자열이 주어진다. 문자열은 =로 끝나며, 연산자로 시작하지 않는다. =은 항상 문자열의 마지막에만 등장한다. 문자열의 시작 또는 연산자의 바로 다음에 "Z

www.acmicpc.net



문제 해설

영단어로 주어진 수식을 원래의 수식으로 변경하고 계산을 한 후 계산 결과를 다시 영단어로 변환해서 출력해야한다. 문제 해결 과정은 다음과 같다.

  1. 단어로 주어진 수를 모두 숫자로 변환한다.
  2. 구분자까지 포함하는 StringTokenizer를 생성하여 수와 연산자를 구분한다.
  3. 수와 연산자를 담아둘 큐를 각각 생성하여 수와 연산자를 구분하여 저장한다.
  4. 수와 연산자를 꺼내가며 계산을 진행한다.
    • 연산자 바로 다음에 ZERO가 등장하는 경우가 없기 때문에 나눗셈의 예외처리는 하지 않아도 된다.
  5. 첫째 줄에 변환한 원래의 수식을, 둘째 줄에 계산 결과를 영단어로 변환한 문자열을 출력한다.

문제를 해결하는 과정에서 다음 사항들을 주의해야 한다.

  • 연산자는 기존의 사칙 연산과 달리 곱셈, 나눗셈의 우선순위가 없으므로 등장한 순서대로 큐에 삽입한다.
  • 정답 및 계산 과정 중에 나오는 수의 절대값이 최대 \(10^{15}\)로, Int의 범위를 초과하기 때문에 Long으로 변환해야 한다.
  • 문자열로 된 수식에 모든 영단어가 반드시 숫자로 변환된다는 조건이 없다. 따라서 NumberFormatException이 발생하면(= 숫자로 변환되지 않은 문자열이 존재한다면) 수식으로 변환할 수 없으므로 Madness!를 출력하고 프로그램을 종료한다.
  • 수식이 연산자로 시작하지 않고 반드시 =으로 끝나며, =은 수식의 마지막에만 등장한다는 조건이 있다. 즉, 정상적인 수식이라면 수의 개수와 연산자의 개수가 같다는 뜻이 되므로 수의 개수와 연산자의 개수가 다르다면 수식으로 변환할 수 없으므로 Madness!를 출력하고 프로그램을 종료한다.

Code

import java.lang.NumberFormatException
import java.util.LinkedList
import java.util.Queue
import java.util.StringTokenizer

fun main() = with(System.`in`.bufferedReader()) {
    val bw = System.out.bufferedWriter()
    val expression = readLine().stringToNum()
    val st = StringTokenizer(expression, "+-x/=", true)
    val numbers: Queue<Long> = LinkedList()
    val operator: Queue<String> = LinkedList()
    while (st.hasMoreTokens()) {
        st.nextToken().also {
            when (it) {
                "+", "-", "x", "/", "=" -> operator.add(it)
                else -> numbers.add(
                    try {
                        it.toLong()
                    } catch (e: NumberFormatException) {
                        println("Madness!")
                        return@with
                    }
                )
            }
        }

    }
    if (numbers.size != operator.size) {
        println("Madness!")
        return@with
    }
    var result = numbers.poll()
    while (operator.isNotEmpty()) {
        when (operator.poll()) {
            "+" -> result += numbers.poll()
            "-" -> result -= numbers.poll()
            "x" -> result *= numbers.poll()
            "/" -> result /= numbers.poll()
        }
    }
    bw.write("$expression\n")
    bw.write(result.toString().numToString())
    bw.close()
}

fun String.stringToNum() = this
    .replace("ONE", "1")
    .replace("TWO", "2")
    .replace("THREE", "3")
    .replace("FOUR", "4")
    .replace("FIVE", "5")
    .replace("SIX", "6")
    .replace("SEVEN", "7")
    .replace("EIGHT", "8")
    .replace("NINE", "9")
    .replace("ZERO", "0")

fun String.numToString() = this
    .replace("1", "ONE")
    .replace("2", "TWO")
    .replace("3", "THREE")
    .replace("4", "FOUR")
    .replace("5", "FIVE")
    .replace("6", "SIX")
    .replace("7", "SEVEN")
    .replace("8", "EIGHT")
    .replace("9", "NINE")
    .replace("0", "ZERO")

댓글