문제출저
https://www.acmicpc.net/problem/2608
2608번: 로마 숫자
첫째 줄과 둘째 줄에 하나씩 로마 숫자로 표현된 수가 주어진다. 입력된 각 수는 2000 보다 작거나 같고, 두 수의 합은 4000보다 작다.
www.acmicpc.net
문제분석
로마 숫자로 2개가 입력값으로 주어진다.
이 숫자를 더한 결과를 로마 숫자와 아라비아 숫자로 표시해야 한다.
로마 숫자에 대응되는 아라비아 숫자를 기록하기 위해 map 자료형을 사용했다.
정답을 구하기 위해 필요한 함수는 두 가지 이다.
로마 숫자를 아라비아 숫자로 바꾸는 함수
아라비아 숫자를 로마 숫자로 바꾸는 함수
로마 숫자 -> 아라비아 숫자 함수
로마 숫자를 하나씩 읽으면서 대응되는 숫자를 더한다.
이 때 현재 읽는 것과 그 전에 읽었던 것을 변수로 두어 저장한다. (now : 현재 저장, before 저장)
현재 읽는 것이 전에 읽던 것보다 크면 4, 9 자리인 경우이다. (예시 IV, IX...)
이 때 현재값을 더하면서 전에 값을 두 번 빼준다. (이미 한 번 더 해진거와 앞으로 뺄거 해서 총 2번 빼준다.)
즉 IV와 같은 경우
I를 읽었을 때 +1 되었을 것이고 V를 읽을 때 +5를 할 것 이다. 이 때 현재값은 5이고 전에 값은 1이므로 4, 9와 위에 말한 조건이 성립된다.
이미 더 해진 I를 빼고 앞으로 한 번 더 I를 빼어 4가 나오게 된다.
이 규칙을 함수로 구현했다.
아라비아 숫자 -> 로마 숫자
일단 천, 백, 십, 일의 각 자릿수를 구한다.
천의 자리는 문제의 조건으로 인해 4000 미만 이므로 자릿수만큼 M을 추가하면 된다.
백, 십, 일은 규칙을 정했다.
함수의 입력값으로 자릿값, 1의 단위, 5의 단위, 10의 단위를 입력했다.
규칙은 자릿값의 수만큼 달라진다.
자릿값이 1~3인 경우
1의 단위를 자릿값만큼 곱한다.
자릿값이 4인 경우
1의 단위 + 5의 단위
자릿값이 5인 경우
5의 단위
자릿값이 6~8인 경우
5의 단위 + 1의 단위 * (자릿값 - 5)
자릿값이 9인 경우
1의 단위 + 10의 단위
만약 100의 자리의 문자를 구할려 할 때 입력값은 다음과 같다.
(자릿값, "C", "D", "M")
위의 규칙에 맞는 함수들을 구현해 문제를 풀 수 있었다.
소스코드
package bakjoon;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
public class b2608로마숫자 {
// 로마자에 대응하는 숫자를 저장하기 위한 map
static Map<Character, Integer> map;
// 입력값1
static String str1;
// 입력값2
static String str2;
public static void main(String[] args) throws IOException {
// 로마 숫자에 대응하는 아라비아 숫자 저장
map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
str1 = br.readLine();
str2 = br.readLine();
// 로마 숫자, 아라비아 숫자로 변환
int num1 = romaToInteger(str1);
int num2 = romaToInteger(str2);
int answer1 = num1 + num2;
// 아라비아 숫자를 로마 숫자로 변환
String answer2 = IntegerToRoma(answer1);
StringBuilder sb = new StringBuilder();
sb.append(answer1).append("\n").append(answer2);
System.out.println(sb);
}
// 로마 문자를 int로 변환
// 로마 숫자의 문자와 그 전의 탐색했던 문자를 저장한다.
// 현재의 문자에 대응하는 값을 더하면서 진행한다.
// 전의 문자가 현재 문자보다 작다면 4와 9인 경우
// 4와 9인 경우는 앞에 더한 값의 *2 만큼 뺀다.
public static Integer romaToInteger(String str) {
int before = 0; // 전의 값
int result = 0; // 현재 값
for (int i = 0; i < str.length(); i++) {
int now = map.get(str.charAt(i)); // 현재값 획득
// 과거값이 현재값보다 작을 때 -> 4와 9인 경우
if(before != 0 && before < now) {
result = result + now - before * 2; // 앞에서 더한 과거값을 빼고 또 과거값을 뺀다
before = now;
}
// 그렇지 않다면 현재 문자에 대응되는 숫자를 더하면서 진행한다.
else {
before = now;
result = result + now;
}
}
return result;
}
// 아라비아 숫자를 로마 숫자로 변환
public static String IntegerToRoma(int num) {
String result = "";
// 1 2 3 / 6 7 8
// 4 9 40 90 400 900
int cheon = num / 1000; // 천 단위
for (int i = 0; i < cheon; i++) {
result = result + "M";
}
num = num % 1000;
// convert 함수를 활용해 쉽게 변환
int bak = num / 100; // 백 단위
result = result + convert(bak, "C", "D", "M");
num = num % 100;
int sip = num / 10;
result = result + convert(sip, "X", "L", "C");
int one = num % 10;
result = result + convert(one, "I", "V", "X");
return result;
}
// 규칙에 맞게 아라비아 숫자를 로마 숫자로 변환해준다.
// 1 ~ 3 : 갯수만큼 1의 단위 문자 사용
// 4 : 1의 단위 + 5의 단위
// 5 : 5의 단위
// 6 ~ 8 : 5의 단위 + -5 갯수만큼 1의 단위
// 9 : 1의 단위 + 10의 단위
public static String convert(int num, String one, String five, String ten) {
String result = "";
if (num >= 1 && num <= 3) {
for (int i = 0; i < num; i++) {
result = result + one;
}
}
else if(num == 4) {
result = one + five;
}
else if(num == 5) {
result = five;
}
else if(num >= 6 && num <= 8) {
result = result + five;
for (int i = 0; i < num - 5; i++) {
result = result + one;
}
}
else if(num == 9) {
result = one + ten;
}
return result;
}
}