백준[3425] 고스택

박지호·2022년 7월 4일
0

백준 3425 고스택

LANGUAGE

JAVA 사용.

INPUT

입력파트는 두가지 프로그램과 입력영역이다.
즉, END가 나타나기 이전까지 stack이 어떤 계산과정을 거칠 것인지를 표현하는 프로그램 영역과 이 프로그램에 의해 계산되는 stack의 초기 숫자들이 담긴다.
그리고 QUIT이 입력되면 프로그램은 종료된다.

OUTPUT

각각 입력값에 대해서 프로그램을 수행한 후 그 결과를 출력한다.
그리고 만약 계산이 불가하거나 맨 마지막에 STACK에 남는 숫자가 둘 이상이라면 "ERROR"를 출력해준다.

동작과정

문제가 길고 입력 방식이 특이하여 처음에 이해를 잘못할 수도 있다.(찬찬히 읽어보면 파악이 되지만...)
동작과정을 정리해보자면 아래 그림과 같다.

CODE

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

public class Go_Stack {
	public static ArrayList<String> list = new ArrayList<>(); // 프로그램 과정을 담을 LIST 선언 (MOD,SUB,DUP 등의 문자가 담기도록 한다.)
	public static boolean condition = true; // ERROR가 중복 출력되지 않게 하기 위하여 선언.
	public static void main(String[] args) throws IOException {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String temp;
		
		// QUIT가 입력될 때 까지 수행한다.
		while(true) {
			list.clear(); // 프로그램과 그 프로그램의 입력값 계산이 끝나면 다음 프로그램을 list에 새로 저장해주어야 한다. 따라서 list를 비운다.
			String str = br.readLine();
			
			
			if (str.equals("")) { //""이 입력되었다면 다음줄을 읽어주어야 한다.
				str = br.readLine();
			}
			
			if(str.equals("QUIT")) { //"QUIT" 입력 시 while문을 종료한다.	
				break;
			}
			while (!str.equals("END")) { //한 프로그램을 list에 저장한다.
                String[] splitLine = str.split(" ");

                // NUM X 제외 하고는 split하였을 때 길이가 1이다.
                // NUM X의 경우 NUM과 X를 따로따로 저장해준다.
                
                // 예를 들어 
                // DUP
                // NUM 2
                // 이렇게 입력된다면 list에는 [DUP,NUM,2]가 저장될 것이다.
                if (splitLine.length == 1) {
                    list.add(splitLine[0]);
                } else {
                    list.add(splitLine[0]);
                    list.add(splitLine[1]);
                }

                str = br.readLine();
            }
			
			str = br.readLine();
			int num = Integer.parseInt(str); //  위 프로그램으로 수행할 입력값의 개수를 받는다.
			
			int []test = new int[num];
			for(int i = 0; i<num;i++) { // 입력값 저장
				str = br.readLine();
				test[i] = Integer.parseInt(str);
			}
			
			
			int point = 0; // stack의 pointer 초기화
			for(int i = 0; i< num; i++) {
				long[] stack = new long[1000]; // stack 초기화
				point = 0; //point 초기화
				condition = true;
				stack[point] = test[i]; // stack에 입력값을 우선 넣는다.
				point++; 
				
				for(int j = 0; j<list.size();j++) {
					temp = list.get(j); // 프로그램 명령어를 하나씩 차례대로 받는다.
					if(temp.equals("NUM")) { //NUM이 나올 경우
						stack[point] = Integer.parseInt(list.get(j+1)); // NUM 다음에는 숫자가 나온다 -> stack에 쌓는다.
						j++;
						point++;
					}
					else if(temp.equals("POP")) { // POP이 나올 경우
						if(point < 1) { // 만약 POP할 문자가 없다면
							System.out.println("ERROR"); //ERROR
							condition = false;
							break;
						}
						point--; // stack의 point를 하나 줄여준다 -> pop과 같은 기작
					}
					else if(temp.equals("INV")) { //INV가 나올경우
						if(point < 1) { // 연산할 대상이 없다면 ERROR
							System.out.println("ERROR");
							condition = false;
							break;
						}
						stack[point-1] = (-1) * stack[point-1]; // EX. 42 -> -42
					}
					else if(temp.equals("DUP")) { // DUP이 나올 경우
						if(point < 1) { // 연산 대상이 없다면 ERROR
							System.out.println("ERROR");
							condition = false;
							break;
						}
						stack[point] = stack[point-1]; //첫번째 숫자를 복사하여 그 위에 올린다.
						point++;
					}
					else if(temp.equals("SWP")) { // SWP이 나올 경우 -> 첫번째 수와 두번째 수 교체
						if(point<2) {
							System.out.println("ERROR");
							condition = false;
							break;
						}
						long temp_num;
						temp_num = stack[point-1];
						stack[point-1] = stack[point-2];
						stack[point-2] = temp_num;					
					}
					else if(temp.equals("ADD")) { // ADD가 나올 경우 제한 조건을 넘기거나 연산 대상이 없다면 ERROR
						if(point<2 || stack[point-2] + stack[point-1] > 1000000000) {
							System.out.println("ERROR");
							condition = false;
							break;
						}
						
						stack[point-2] = stack[point-1] + stack[point-2]; // 아니면 첫번째 수와 두번째 수를 더해준다.
						point--;
					}
					else if(temp.equals("SUB")) { // SUB가 나올 경우 제한 조건을 넘기거나 연산 대상이 없다면 ERROR
						if(point<2 || Math.abs(stack[point-2] - stack[point-1]) > 1000000000) {
							System.out.println("ERROR");
							condition = false;
							break;
						}
						stack[point-2] = stack[point-2] - stack[point-1];
						point--;
					}
					else if(temp.equals("MUL")) { // MUL이 나올 경우 제한 조건을 넘기거나 연산 대상이 없다면 ERROR
						if(point<2 || Math.abs(stack[point-2] * stack[point-1]) > 1000000000) {
							System.out.println("ERROR");
							condition = false;
							break;
						}
						stack[point-2] = stack[point-2] * stack[point-1];
						point--;
					}
					else if(temp.equals("DIV")) {
						if(point<2 || stack[point-1] == 0) { // DIV가 나올 경우 0으로 나누게 되거나 연산 대상이 없다면 ERROR
							System.out.println("ERROR");
							condition = false;
							break;
						}
						stack[point-2] = stack[point-2] / stack[point-1];
						point--;
					}
					// MOD가 나올 경우 0으로 나누게 되거나 연산 대상이 없다면 ERROR
					else {
						if(point<2 || stack[point-1] == 0) {
							System.out.println("ERROR");
							condition = false;
							break;
						}
						stack[point-2] = stack[point-2] % stack[point-1];
						point--;
					}
				}
				
				if(point != 1 && condition == true) { // stack에 하나 이상의 수가 있다면 ERROR
					System.out.println("ERROR");
				}
				else if (condition == false) {
					
				}
				else { // ERROR가 아닌 정상적인 경우라면 stack에 있는 원소를 출력한다.
					System.out.println(stack[0]);
				}
				
				
			}
			if(!str.equals("QUIT"))
				System.out.println();
		}
	}
}

check

  • 문제 파악만 한다면 난이도가 높지 않은 구현 문제였다.
  • 예외 처리를 꼼꼼하게!

0개의 댓글