베오
DCode
베오
전체 방문자
오늘
어제
  • 분류 전체보기 (218)
    • 공지사항 (1)
    • 잡설 (1)
    • Programming (33)
      • [C] (1)
      • [Java] (4)
      • [Python] (2)
      • [Android] (2)
      • [Network] (0)
      • [Operation System] (2)
      • [Spring Boot] (22)
      • [Docker] (0)
    • Algorithm (31)
      • 자료구조 (2)
      • 알고리즘 (Java) (14)
      • 알고리즘 (기초) (15)
    • Coding Test (131)
      • BOJ (131)
      • Algospat (0)
    • 이론적인거 (14)
      • 보안 (5)
      • 오류 해결 (2)
      • 디자인 패턴 (5)
      • 네트워크 (1)
      • 기타 (1)
    • 최신기술 (4)
      • 블록체인 (1)
    • [Project] (1)

블로그 메뉴

  • 🐈‍⬛ GitHub
  • 📫 방명록
  • 🔖 태그

공지사항

인기 글

티스토리

hELLO · Designed By 정상우.
베오

DCode

Coding Test/BOJ

[BOJ/JAVA] 1287번: 할 수 있다

2022. 9. 8. 13:37

https://www.acmicpc.net/problem/1287

 

1287번: 할 수 있다

곱하기가 연산자 우선순위가 빠르므로 5+(1+2)*3 = 5+3*3 = 5+9 = 14가 된다. 연산자의 우선순위는 다음과 같다. (), */, +- 여기서 *와 /가 연산자 우선순위가 같고, +와 -가 연산자 우선순위가 같다. ()가

www.acmicpc.net

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;

// 9 498 * 9 499
// int X
// long X
// BigInteger

public class java_1287 {

    // 숫자 추출
    static Queue<String> extractNumber(String mathExpression) {
        Queue<String> mathQueue = new LinkedList<>();

        StringBuffer number = new StringBuffer();
        for (int i = 0; i < mathExpression.length(); i++) {
            // 현재 값이 숫자라면
            if (Character.isDigit(mathExpression.charAt(i))) {
                number.append(mathExpression.charAt(i));
            }
            // 숫자가 아닌 경우, 앞에 숫자를 처리 했는가에 따라 달라짐
            else {
                if (number.length() != 0) {
                    mathQueue.add(number.toString());
                    number = new StringBuffer();
                }
                mathQueue.add(mathExpression.substring(i, i + 1));
            }
        }

        if (number.length() != 0) {
            mathQueue.add(number.toString());
            number = new StringBuffer();
        }

        return mathQueue;
    }

    static BigInteger calc(BigInteger a, BigInteger b, String calc) {
        BigInteger result = null;

        switch (calc) {
            case "+":
                result = a.add(b);
                break;
            case "-":
                result = a.subtract(b);
                break;
            case "*":
                result = a.multiply(b);
                break;
            case "/":
                result = a.divide(b);
                break;
            default:
                return null;
        }

        return result;
    }

    // 괄호 부분 계산
    static BigInteger subCalculator(Queue<String> mathQueue) {
        BigInteger result = null;

        Deque<String> operationStack = new LinkedList<>();
        Deque<BigInteger> operandStack = new LinkedList<>();

        boolean isBracket = false;

        while (!mathQueue.isEmpty()) {
            String tmp = mathQueue.poll();
            // ) 를 만나면 종료
            if (tmp.equals(")")) {
                isBracket = true;
                break;
            }

            // 숫자면 숫자 스택에 삽입
            if (Character.isDigit(tmp.charAt(0))) {
                operandStack.addLast(new BigInteger(tmp));

                // // 만약 operationStack 가장 위가 * / 라면...
                if (!operationStack.isEmpty()) {
                    if (operationStack.peekLast().equals("*") || operationStack.peekLast().equals("/")) {
                        // 계산 해야하는데 operand가 없다면 -> 오류처리
                        if (operandStack.size() < 2) {
                            return null;
                        }

                        // b 뽑고 a 뽑기 LIFO
                        BigInteger operandB = operandStack.removeLast();
                        BigInteger operandA = operandStack.removeLast();

                        String operator = operationStack.removeLast();

                        BigInteger calcResult = calc(operandA, operandB, operator);
                        if (calcResult == null) {
                            return null;
                        }
                        operandStack.addLast(calcResult);
                    }
                }
            }

            // 사칙연산 분리하기
            else {
                switch (tmp) {
                    case "+":
                        operationStack.addLast(tmp);
                        break;
                    case "-":
                        operationStack.addLast(tmp);
                        break;
                    case "*":
                        operationStack.addLast(tmp);
                        break;
                    case "/":
                        operationStack.addLast(tmp);
                        break;
                    case "(":
                        BigInteger calcResult = subCalculator(mathQueue);
                        if (calcResult == null) {
                            return null;
                        }
                        // mathQueue.addFirst(calcResult.toString());
                        operandStack.addLast(calcResult);
                        // // 만약 operationStack 가장 위가 * / 라면...
                        if (!operationStack.isEmpty()) {
                            if (operationStack.peekLast().equals("*") || operationStack.peekLast().equals("/")) {
                                // 계산 해야하는데 operand가 없다면 -> 오류처리
                                if (operandStack.size() < 2) {
                                    return null;
                                }

                                // b 뽑고 a 뽑기 LIFO
                                BigInteger operandB = operandStack.removeLast();
                                BigInteger operandA = operandStack.removeLast();

                                String operator = operationStack.removeLast();

                                calcResult = calc(operandA, operandB, operator);
                                if (calcResult == null) {
                                    return null;
                                }
                                operandStack.addLast(calcResult);
                            }
                        }
                        break;
                    default:
                        return null;
                }
            }

            // operand 보다 operator가 더 많으면 오류.
            if (operandStack.size() < operationStack.size()) {
                return null;
            }

        }

        // 닫는 괄호 없이 빠져나왔다면 오류
        if (!isBracket) {
            return null;
        }

        // 스택을 빠져 나왔을 때,
        // operandSize == operationSize + 1 여야 함
        if (operandStack.size() != operationStack.size() + 1) {
            return null;
        }

        // 남은 스택 뽑으면서 연산하기
        while (!operationStack.isEmpty()) {
            // b 뽑고 a 뽑기 LIFO
            BigInteger operandA = operandStack.removeFirst();
            BigInteger operandB = operandStack.removeFirst();

            String operator = operationStack.removeFirst();

            BigInteger calcResult = calc(operandA, operandB, operator);
            if (calcResult == null) {
                return null;
            }
            operandStack.addFirst(calcResult);
        }

        if (operandStack.size() == 1) {
            result = operandStack.pop();
        } else {
            return null;
        }

        return result;
    }

    // 일단 괄호 없이 연산해보자
    public static BigInteger calculator(Queue<String> mathQueue) {
        BigInteger result = null;

        Deque<String> operationStack = new LinkedList<>(); // + - * /
        Deque<BigInteger> operandStack = new LinkedList<>(); // 숫자

        while (!mathQueue.isEmpty()) {
            String tmp = mathQueue.poll();

            // 숫자면 숫자 스택에 삽입
            if (Character.isDigit(tmp.charAt(0))) {
                operandStack.addLast(new BigInteger(tmp));

                // // 만약 operationStack 가장 위가 * / 라면...
                // 1, 2
                // *
                // 1 * 2
                if (!operationStack.isEmpty()) {
                    if (operationStack.peekLast().equals("*") || operationStack.peekLast().equals("/")) {
                        // 계산 해야하는데 operand가 없다면 -> 오류처리
                        if (operandStack.size() < 2) {
                            return null;
                        }

                        // b 뽑고 a 뽑기 LIFO
                        BigInteger operandB = operandStack.removeLast();
                        BigInteger operandA = operandStack.removeLast();

                        String operator = operationStack.removeLast();

                        BigInteger calcResult = calc(operandA, operandB, operator);
                        if (calcResult == null) {
                            return null;
                        }
                        operandStack.addLast(calcResult);
                    }
                }
            }

            // 사칙연산 분리하기
            else {
                switch (tmp) {
                    case "+":
                        operationStack.addLast(tmp);
                        break;
                    case "-":
                        operationStack.addLast(tmp);
                        break;
                    case "*":
                        operationStack.addLast(tmp);
                        break;
                    case "/":
                        operationStack.addLast(tmp);
                        break;
                    case "(":
                        // ((4-3))
                        BigInteger calcResult = subCalculator(mathQueue);
                        if (calcResult == null) {
                            return null;
                        }
                        // mathQueue.addFirst(calcResult.toString());
                        operandStack.addLast(calcResult);
                        // // 만약 operationStack 가장 위가 * / 라면...
                        if (!operationStack.isEmpty()) {
                            if (operationStack.peekLast().equals("*") || operationStack.peekLast().equals("/")) {
                                // 계산 해야하는데 operand가 없다면 -> 오류처리
                                if (operandStack.size() < 2) {
                                    return null;
                                }

                                // b 뽑고 a 뽑기 LIFO
                                BigInteger operandB = operandStack.removeLast();
                                BigInteger operandA = operandStack.removeLast();

                                String operator = operationStack.removeLast();

                                calcResult = calc(operandA, operandB, operator);
                                if (calcResult == null) {
                                    return null;
                                }
                                operandStack.addLast(calcResult);
                            }
                        }
                        break;
                    default:
                        return null;
                }
            }

            // operand 항상 2개 이상
            // operand 의 수 > operator

            // operand 보다 operator가 더 많으면 오류.
            if (operandStack.size() < operationStack.size()) {
                return null;
            }

        }

        // 스택을 빠져 나왔을 때,
        // operandSize == operationSize + 1 여야 함
        if (operandStack.size() != operationStack.size() + 1) {
            return null;
        }

        // 남은 스택 뽑으면서 연산하기
        while (!operationStack.isEmpty()) {
            // b 뽑고 a 뽑기 LIFO
            BigInteger operandA = operandStack.removeFirst();
            BigInteger operandB = operandStack.removeFirst();

            String operator = operationStack.removeFirst();

            BigInteger calcResult = calc(operandA, operandB, operator);
            if (calcResult == null) {
                return null;
            }
            operandStack.addFirst(calcResult);
        }

        if (operandStack.size() == 1) {
            result = operandStack.pop();
        } else {
            return null;
        }

        return result;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        // 스택에 저장하여 연산하자

        // 수식 입력받기
        String mathExpression = br.readLine();

        Queue<String> mathQueue = extractNumber(mathExpression);

        BigInteger result = calculator(mathQueue);

        if (result == null) {
            System.out.println("ROCK");
        } else {
            System.out.println(result);
        }

        // 곱하기 더하기 우선순위를 어떻게 계산하는가?

        // 1 + (2 + 3 * 4) * 5 의 경우
        // 1 + ( 2 + 3 * 4 )

        // 괄호의 경우 재귀 호출하기
        // -> 언제까지? -> ) 만날 때 까지
        // 계산 결과 반환

        // 2 + 3 * 4 의 경우
        // 2 push
        // + push
        // 3 push
        // * push
        // 4 -> 1. 숫자라면 pop op, pop num 해서 연산하기
        // -> 2. 괄호라면 재귀 호출

        br.close();
        bw.close();
    }
}
저작자표시 (새창열림)

'Coding Test > BOJ' 카테고리의 다른 글

[BOJ/JAVA] 11780번: 플로이드 2  (2) 2022.09.26
[BOJ/JAVA] 11265번: 끝나지 않는 파티  (0) 2022.09.26
[BOJ/JAVA] 11866번: 요세푸스 문제 0  (0) 2022.09.08
[BOJ/JAVA] 2064번: IP 주소  (0) 2022.09.08
[BOJ/JAVA] 1715번: 카드 정렬하기  (0) 2022.08.27
    'Coding Test/BOJ' 카테고리의 다른 글
    • [BOJ/JAVA] 11780번: 플로이드 2
    • [BOJ/JAVA] 11265번: 끝나지 않는 파티
    • [BOJ/JAVA] 11866번: 요세푸스 문제 0
    • [BOJ/JAVA] 2064번: IP 주소
    베오
    베오

    티스토리툴바