거북이처럼 천천히

알고리즘 (6월 16일) 본문

Algorithm/알고리즘 문제 풀이

알고리즘 (6월 16일)

유로 청년 2022. 6. 16. 18:17

1. 문제 (코딩도장, 이상한 계산기)

https://codingdojang.com/scode/590?langby=java#answer-filter-area 

 

코딩도장

프로그래밍 문제풀이를 통해서 코딩 실력을 수련

codingdojang.com


2. 생각

괄호가 없는 사칙연산 식을 입력받았을 때 오른쪽에서부터, 더하기나 빼기를 곱하기나 나누기보다 먼저 계산한 결과를 리턴하는 코드를 작성하라.

 

(단, 사칙연산 식은 문자열의 형식으로 입력받는다)

 

  1. 문자열 형식으로 괄호가 없는 사칙연산 식을 입력받는다.
  2. 입력받은 식내에 공백(space)을 제거한다.
  3. while문과 for문을 이용하여 앞에서부터 문자열을 하나씩 쪼개서 해당 부분이 연산기호(+, -, /, *)인지 여부 확인
    → 만약 해당 부분이 연산기호라면, 이전 문자열들은 숫자라고 판단하여 이전 문자열과 연산 기호로 인식된 부분을 
        각각 잘라서 리스트에 "elements" 리스트에 저장한다.
    "elements" 리스트에 저장한 후, 해당 숫자와 기호를 원래 String에서 삭제한다.
    → 위 작업을 반복하여 숫자와 연산기호를 분리하여 "elements" 리스트에 저장한다.
  4. 이중 for문을 이용하여 "elements" 리스트 뒤에서부터 하나씩 원소를 뽑아서 해당 원소가 "+" or "-"인지 확인
    해당 원소가 "+" or "-"아라면 앞 뒤 원소는 무조건 숫자이기 때문에 앞뒤 숫자끼리 계산한다.
    → 그 전에 계산하는 숫자와 연산기호를 제외한 나머지 원소들을 "result" 리스트에 임시 저장하고, 연산 결과를 
        "result" 리스트에 임시 저장한다.
  5. "elements"리스트를 비우고 "result"리스트를 "elements" 리스트에 복붙한다. 그리고, "elements"리스트를 비운다.
  6. 4번 ~ 5번까지 과정을 "x"와 "/" 연산에 적용하여 반복한다.
  7. 최종 연산 결과는 "elements" 리스트에 저장되어 있기 때문에 "elements" 리스트를 출력한다.

3. 풀이 및 코드 분석

import java.util.ArrayList;
import java.util.Scanner;
import java.util.List;

public class calculator {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		ArrayList<String> elements = new ArrayList<>();
		ArrayList<String> result = new ArrayList<>();

		// 입력
		System.out.print("괄호가 없는 사칙연산식 입력:");
		String equation = scan.nextLine();
		String[] signs = {"+", "-", "*", "/"};

		// 숫자, 기호 분리해서 리스트에 저장하기
		equation = equation.replaceAll(" ", "");
		while(equation.length()>0) {
			// equation내에 연산 기호가 없으면 숫자만 있다고 판단하여 리스트에 저장
			if(equation.contains("+")==false&equation.contains("-")==false&
			   equation.contains("*")==false&equation.contains("/")==false) {
					elements.add(equation);
					equation = "";
			}
			
			loop1 :
			for(int i=0; i<equation.length(); i++) {
				String element = equation.substring(i, i+1);
				
				loop2 :
				for(String sign : signs) {
					if(element.equals(sign)) {
						// 연산 기호 앞에 있는 숫자를 리스트에 저장
						elements.add(equation.substring(0, i));
						// 연산 기호를 리스트에 저장
						elements.add(equation.substring(i, i+1));
						// 리스트에 저장하지 않는 부분을 잘라서 다시 equation에 저장
						equation = equation.substring(i+1, equation.length());
						break loop1;
					}
				}
			}
		}
		
		// +과 -부터 계산
		String[] firstSigns = {"+", "-"};
		loop3 :
		for(int i=elements.size()-1; i>=0; i--) {
			loop4 :
			for(String sign : firstSigns) {
				if(elements.get(i).equals(sign)) {
					// i-2번째까지 elements 객체들을 result 리스트에 임시 저장
					for(int j=0; j<i-1; j++) {
						result.add(elements.get(j));
					}				
					
					// 숫자들을 eleements 리스트에서 뽑아서 double형으로 변환
					double m = Double.parseDouble(elements.get(i-1));
					double n = Double.parseDouble(elements.get(i+1));
					
					// 계산하고 result 리스트에 저장
					if(sign.equals("+")) {
						result.add(String.valueOf(m+n));
					}else {
						result.add(String.valueOf(m-n));
					}
					
					// 나머지 부분 result 리스트에 저장
					for(int j=i+2; j<elements.size(); j++) {
						result.add(elements.get(j));
					}
					
					// result 리스트를 elements 리스트에 복사 붙어넣기
					elements.clear();
					for(int j=0; j<result.size(); j++) {
						elements.add(result.get(j));
					}						
					result.clear();
					break loop4;
				}
			}
		}
		
		// *과 / 계산
		String[] secondSigns = {"*", "/"};
		loop5 :
		for(int i=elements.size()-1; i>=0; i--) {
			loop6 :
			for(String sign : secondSigns) {
				if(elements.get(i).equals(sign)) {
					// i-2번째까지 elements 객체들을 result 리스트에 임시 저장
					for(int j=0; j<i-1; j++) {
						result.add(elements.get(j));
					}				
					
					// 숫자들을 eleements 리스트에서 뽑아서 double형으로 변환
					double m = Double.parseDouble(elements.get(i-1));
					double n = Double.parseDouble(elements.get(i+1));
					
					// 계산하고 result 리스트에 저장
					if(sign.equals("*")) {
						result.add(String.valueOf(m*n));
					}else {
						result.add(String.valueOf(m/n));
					}
					
					// 나머지 부분 result 리스트에 저장
					for(int j=i+2; j<elements.size(); j++) {
						result.add(elements.get(j));
					}
					
					// result 리스트를 elements 리스트에 복사 붙어넣기
					elements.clear();
					for(int j=0; j<result.size(); j++) {
						elements.add(result.get(j));
					}						
					result.clear();
					break loop6;
				}
			}
		}

		// 결과 출력
		for(int i=0; i<elements.size(); i++) {
			System.out.println("결과: "+elements.get(i));
		}
	}
}

4. 메모

  • 이중 for문 탈출 
    ▶ 각각의 for문에게 라벨(label)명을 부여함으로써 필요에 따라 해당 for문에서 탈출할 수 있다.
public class calculator {
	public static void main(String[] args) {
		loop1 :
		for(int i=0; i<2; i++) {
			loop2 :
			for(int j=0; j<2; j++) {
				System.out.printf("i: %d, j: %d\n", i, j);
				
				if(j==1) {
					break loop1;
				}
			}
		}
	}
}
i: 0, j: 0
i: 0, j: 1

    ▶ 목표: i와 관계없이 j==1 만 만족하면 이중 for문에서 탈출
         각각의 for문에 라벨명을 "loop1", "loop2"를 붙어줌으로서 필요에 따라 탈출하고 싶은 for문을 탈출할 수 있다.

 

 

'Algorithm > 알고리즘 문제 풀이' 카테고리의 다른 글

알고리즘 (6월 22일)  (0) 2022.06.23
알고리즘 (6월 19일)  (0) 2022.06.19
알고리즘 (6월 15일)  (0) 2022.06.15
알고리즘 (6월 13일) - (3)  (0) 2022.06.13
알고리즘 (6월 13일) - (2)  (0) 2022.06.13