본문 바로가기
알고리즘

[JAVA]백준 3425번: 고스택

by Kwoncorin 2021. 7. 19.
728x90

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

 

3425번: 고스택

각각의 입력값에 대해서, 해당하는 프로그램을 수행한 뒤, 출력값을 출력하면 된다. 출력값이란 스택에 저장되어 있는 숫자이다. 만약, 프로그램 에러가 발생하거나, 모든 수행이 종료됐을 때

www.acmicpc.net

 

1. 문제 설명

 

창영이가 스택을 변형해서 고 스택을 만들었다.

 

스택에 가장 위에 저장된 수를 첫 번째 수, 그다음은 차례대로 두 번째 수, 세 번째 수라고 할 때

 

NUM X : X를 스택 가장 위에 저장

POP : 스택 가장 위의 숫자 제거

INV : 첫번째 수의 부호를 바꾼다

DUP : 첫번째 숫자를 하나 더 스택의 가장 위에 저장

SWP : 첫번째 수와 두 번째 수 위치 바꿈

ADD : 첫번쨰 수와 두 번째 수 더함

SUB : 두번째 수에서 첫 번째 수 뺌

MUL : 첫번째 수와 두 번째 수 곱합

DIV : 첫 번째 숫자로 두 번째 수를 나눈 몫

MOD : 첫 번째 숫자로 두 번째 숫자를 나눈 나머지

 

총 10가지의 연산을 수행한다.

 

숫자가 부족해서 연산을 수행할 수 없을 때, 0으로 나누었을 때, 연산 결과의 절댓값이 10^9를 넘어갈 때는 ERROR를 출력한다.

 

2. 풀이

 

그대로 구현하면 되는 문제이다.

 

신경 써야 할 것들이 몇 가지 있는데

 

1. ERROR

- 연산을 수행하는 숫자가 부족한 경우 (POP, INV, DUP -> 스택에 한 개 이상 숫자가 있어야 함, SWP, ADD, SUB, MUL, DIV, MOD -> 스택에 두 개 이상 숫자가 있어야 함)

- 0으로 나누는 경우 (DIV, MOD)

- 연산 결과의 절댓값이 10^9를 넘어가는 경우 (ADD, SUB, MUL)

 

2. QUIT, END

- QUIT가 나오면 전체 프로그램 종료

- END가 나오면 현재 기계 설명 종료

 

5번 정도 틀렸는데, END를 제대로 구현하지 못해서 틀렸다.

 

먼저, 처음 입력받은 문자열이 QUIT인지 확인 후, do while문을 사용하여 END인지 확인하지 않고 바로 연산 list에 저장했다.

이럴 경우

END
1
1

위와 같은 예제에서 틀리게 된다.

 

처음 입력받은 문자열이 quit인지 확인 후, end인지 확인하고 연산 list에 저장해야 한다.

 

가능하면 do while문은 쓰지 않는 게 생각하지 못한 예제를 통과하는 것에 도움이 될 것 같다.

 

3. 코드

 

import java.io.*;
import java.util.*;

public class Main {

    public static ArrayList<String> list = new ArrayList<>();
    public static long[] stack = new long[1001];
    public static int head = 0;
    public static int MAX = 1000000000;

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        StringBuilder sb = new StringBuilder();

        while (true) {
            list.clear();

            String line = br.readLine();


            // QUIT일 경우 다음 기계 설명이 없음.
            if (line.equals("QUIT")) {
                break;
            }

            // END가 나올때까지 명령 입력
            while (!line.equals("END")) {
                String[] splitLine = line.split(" ");

                // POP, INV, DUP, SWP, ADD, SUB, MUL, DIV, MOD
                if (splitLine.length == 1) {
                    list.add(splitLine[0]);
                } else {
                    // NUM X
                    list.add(splitLine[0]);
                    list.add(splitLine[1]);
                }

                line = br.readLine();
            }





            int test_case = Integer.parseInt(br.readLine());

            for (int x = 0; x < test_case; x++) {
                int num = Integer.parseInt(br.readLine());

                if (runProgram(num)) {
                    sb.append(stack[0]).append("\n");
                } else {
                    sb.append("ERROR\n");
                }
            }

            sb.append("\n");
            br.readLine();

        }
        System.out.println(sb);

    }

    // 입력 값에 대해 프로그램 수행
    public static boolean runProgram(int now) {
        int listSize = list.size();

        // 초기화
        head = 0;
        stack[head++] = now;

        for (int x = 0; x < listSize; x++) {

            if (list.get(x).equals("NUM")) {

                stack[head++] = Long.parseLong(list.get(x + 1));
                x++;
            } else if (list.get(x).equals("POP")) {
                if(head<1)
                    return false;

                head--;

            } else if (list.get(x).equals("INV")) {

                if(head<1)
                    return false;

                stack[head - 1] *= -1;

            } else if (list.get(x).equals("DUP")) {

                if (head < 1) {
                    return false;
                }

                stack[head] = stack[head - 1];
                head++;

            } else if (list.get(x).equals("SWP")) {

                if(head<2)
                    return false;

                long temp = stack[head - 1];
                stack[head - 1] = stack[head - 2];
                stack[head - 2] = temp;
            } else if (list.get(x).equals("ADD")) {

                if(head<2)
                    return false;

                if (Math.abs(stack[head - 1] + stack[head - 2]) > MAX) {
                    return false;
                }

                stack[head - 2] = stack[head - 1] + stack[head - 2];
                head--;

            } else if (list.get(x).equals("SUB")) {
                if(head<2)
                    return false;

                if (Math.abs(stack[head - 2] - stack[head - 1]) > MAX) {

                    return false;
                }

                stack[head - 2] = stack[head - 2] - stack[head - 1];
                head--;


            } else if (list.get(x).equals("MUL")) {
                if(head<2)
                    return false;

                if (Math.abs(stack[head - 2] * stack[head - 1]) > MAX) {
                    return false;
                }

                stack[head - 2] = stack[head - 2] * stack[head - 1];
                head--;
            } else if (list.get(x).equals("DIV")) {
                if(head<2)
                    return false;

                if(stack[head-1]==0)
                    return false;

                stack[head - 2] = stack[head - 2] / stack[head - 1];
                head--;
            } else {
                // MOD

                if(head<2)
                    return false;

                if(stack[head-1]==0)
                    return false;

                stack[head - 2] = stack[head - 2] % stack[head - 1];
                head--;
            }

        }

        // 스택에 저장되어 있느 숫자가 1개가 아니라면 ERROR
        if(head==1)
            return true;
        return false;

    }



}

 

728x90

'알고리즘' 카테고리의 다른 글

[JAVA]백준 1062번: 가르침  (0) 2021.07.19
[JAVA]백준 3055번: 탈출  (0) 2021.07.19
[JAVA]백준 2346번: 풍선 터뜨리기  (0) 2021.05.20
[JAVA]백준 1966번: 프린터 큐  (0) 2021.05.18
[JAVA]백준 1874번: 스택 수열  (0) 2021.05.16