문제풀이/String

[PS] BOJ2608 로마숫자 ( string ) with JAVA

IT록흐 2023. 8. 28. 12:36
반응형
 

2608번: 로마 숫자

첫째 줄과 둘째 줄에 하나씩 로마 숫자로 표현된 수가 주어진다. 입력된 각 수는 2000 보다 작거나 같고, 두 수의 합은 4000보다 작다.

www.acmicpc.net

 

◎ 문제풀이

 

문제가 복잡해 보이나 이해를 하면  어려운 문제는 아니다. 복잡한 개념이 들어가 있지는 않으나 구현력이 필요한 문제였다. 

 

크게 두 가지 과정이 있다.

 

1) 로마 숫자를 십진법 숫자로 만들기

2) 십진법 숫자를 로마숫자로 만들기

 

- 로마 숫자를 십진법 숫자로 만들기

 

1) 로마문자와 십집법 숫자가 매핑된 Map 자료구조를 만든다.

2) 로마숫자를 좌측부터 한 문자씩 읽어온다. 

3) 현재 문자는 이전 문자보다 작아야 한다.

4) 현재 문자가 이전 문자보다 크다면 XL, XC , CD ,CM ... 이런 문자이다. 

5) 각 문자를 Map 자료구조의 key값으로 넣어 십진법 숫자를 가져와 합친다. 

 

 

- 십진법 숫자를 로마숫자로 만들기

 

1) 십진법 숫자와 로마문자가 매핑된 Map 자료구조를 만든다.

2) 1000의 자리부터 1의 자리까지 각 자리의 수를 가져온다.

3)  9, 4인 경우는 XL, XC , CD ,CM ... 이런 문자이고 5보다 큰 경우와 5보다 작은 경우로 나눈다.

 

예를들어,

 

100의 자리가 7이라고 해보자.

7은 5보다 크다. 합으로 표현하면  5 + 1 + 1 이다. 이는 DCC 이다.

 

만약 3이라면

1 + 1 + 1이다. 이는 CCC이다.

 

만약 4라면

100의 자리의 4는 CD이다.

 

이런 원리로 각 자리의 수를 로마문자로 변환해준다.

 

4) 자릿수에 매핑되는 로마문자를 합쳐 문자열을 만든다. 

 

 

◎ 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

//BOJ2608 로마숫자
public class Main {
    static Map<String,Integer> RomeToNumMap = new HashMap<>();
    static Map<Integer,String> NumToRomeMap = new HashMap<>();


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

        String value1 = br.readLine();
        String value2 = br.readLine();
        
        // 로마문자를 십진법으로 변환하기
        int num1 = convertRomeNumToDecimal(value1);
        int num2 = convertRomeNumToDecimal(value2);

        int sum = num1 + num2; 
        
        // 십진법을 로마문자로 변환하기
        String ans = convertDecimalToRomeNum(sum);
        
        // 출력
        System.out.println(sum);
        System.out.println(ans);

    }


    public static void init(){
        // 로마숫자 -> 십집법 Map 자료구조
        RomeToNumMap.put("I",1);
        RomeToNumMap.put("V",5);
        RomeToNumMap.put("X",10);
        RomeToNumMap.put("L",50);
        RomeToNumMap.put("C",100);
        RomeToNumMap.put("D",500);
        RomeToNumMap.put("M",1000);
        RomeToNumMap.put("IV",4);
        RomeToNumMap.put("IX",9);
        RomeToNumMap.put("XL",40);
        RomeToNumMap.put("XC",90);
        RomeToNumMap.put("CD",400);
        RomeToNumMap.put("CM",900);

        // 십진법 숫자 -> 로마숫자 Map 자료구조
        NumToRomeMap.put(1,"I");
        NumToRomeMap.put(5,"V");
        NumToRomeMap.put(10,"X");
        NumToRomeMap.put(50,"L");
        NumToRomeMap.put(100,"C");
        NumToRomeMap.put(500,"D");
        NumToRomeMap.put(1000,"M");
        NumToRomeMap.put(4,"IV");
        NumToRomeMap.put(9,"IX");
        NumToRomeMap.put(40,"XL");
        NumToRomeMap.put(90,"XC");
        NumToRomeMap.put(400,"CD");
        NumToRomeMap.put(900,"CM");
    }

    // 로마숫자를 십진법 숫자로 변경
    public static int convertRomeNumToDecimal(String romeNum){
        int decimal = 0;
        String before = null;

        for(int i =0; i<romeNum.length();i++){
            String curr = String.valueOf(romeNum.charAt(i));

            if(before == null) before = curr; // 이전문자가 null인 경우
            else if(RomeToNumMap.get(before) >= RomeToNumMap.get(curr)) { // 이전문자가 현재문자보다 큰 경우
                decimal += RomeToNumMap.get(before);
                before = curr;
            }else{
                decimal += RomeToNumMap.get(before.concat(curr)); // 이전문자가 현재문자보다 작은 경우
                before = null;
            }
        }

        if(before != null ){ // 마지막 문자
            decimal += RomeToNumMap.get(before);
        }

        return decimal;
    }

    // 십진법 숫자를 로마 숫자로 변경
    public static String convertDecimalToRomeNum(int decimal){
        String ans = "";
        int digit = 1000;

        while(true){
            int m = decimal/digit;
            decimal -= m*digit;

            ans = convert(ans,m,digit);
            if(digit==1) break;
            digit = digit/10;
        }

        return ans;
    }

    // 각 자리수에 맞는 로마숫자로 변경
    private static String convert(String ans, int m, int digit) {
        if( m == 9 ) ans += NumToRomeMap.get(9*digit); 
        else if( m == 4 ) ans += NumToRomeMap.get(4*digit);
        else if ( m >= 5 ) {
            m -= 5;
            ans += NumToRomeMap.get(5*digit);
            while(m-- > 0){
                ans += NumToRomeMap.get(digit);
            }
        }
        else{
            while(m-- > 0){
                ans += NumToRomeMap.get(digit);
            }
        }
        return ans;
    }
}

 

반응형