오늘도 어마어마하고 무시무시한 문제와 마주했다.
문제를 읽고 이해하는데도 시간이 꽤나 걸렸던 것 같다.
<문제>
로마자에서 숫자로 바꾸기
1~3999 사이의 로마자 s를 인자로 주면 그에 해당하는 숫자를 반환해주세요. 로마 숫자를 숫자로 표기하면 다음과 같습니다.Symbol Value I 1 V 5 X 10 L 50 C 100 D 500 M 1000
로마자를 숫자로 읽는 방법은 로마자를 왼쪽부터 차례대로 더하면 됩니다. III = 3 XII = 12 XXVII = 27 입니다.
그런데 4를 표현할 때는 IIII가 아니라 IV 입니다. 뒤의 숫자에서 앞의 숫자를 빼주면 됩니다. 9는 IX입니다.
I는 V와 X앞에 와서 4, 9 X는 L, C앞에 와서 40, 90 C는 D, M앞에 와서 400, 900 입니다.
처음에 애를 먹었던 부분은 아래와 같다.
1. 로마자를 읽는데 서툴러서 계산법에 익숙해지는 것
2. '1~3999 사이', '4, 9 관련 숫자가 예외라는 점' 등에 시선을 뺏겨 시간을 보낸 것
3. 인자로 받는 로마자가 최대 몇 글자로 구성될 수 있는 지 파악해본 것
(지금 다시 생각해보면 크게 중요하지는 않은 부분이었던 것 같다.)
차차 계산법에 익숙해지면서, 어려운 부분보다는 눈에 보이는 규칙을 찾아서 최대한으로 로직을 짜보기로 하고 생각한 부분은,
"인자로 들어온 로마자의 각 문자열을 순서대로 비교했을 때, 왼쪽에 있는 문자열의 값이 오른쪽 값보다 크면 값을 더한다. 반대로 오른쪽 값이 더 크면 오른쪽 값에서 왼쪽 값을 뺀다." 였다.
먼저 심볼과 값을 하나의 객체에 할당해주고, 'result'라는 변수에 0을 할당했다.
그 뒤에 for문과 if문을 섞어서 위의 논리대로 코딩을 했으나 최대 1개만 pass..
계속되는 실패로 너무 지쳐서,
참지 못하고 주변의 조언을 많이 많이 많이 구해서 코드를 수정하여 결국 성공하긴 했다.
function romanToNum(s) {
const roman = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
};
let result = 0;
for (let i = 0; i < s.length; i++) {
if (roman[s[i]] < roman[s[i + 1]]) {
result += roman[s[i + 1]] - roman[s[i]]; i++;
} else {
result += roman[s[i]]
}
} return result;
}
계속 헤맸던건 'else' 부분에 첫 번째 조건의 반대 상황을 'else if'로 추가했던 부분이다.
이렇게 되면 같은 값일 경우 해당되는 조건이 없기 때문에 제대로 된 값을 더해지 못했다.
여기서 예외 상황은 오른쪽 값이 클 때 오른쪽에서 빼주는 것으로만 한정하면 됐고, 그 외의 상황은 그냥 계속 result에 더해주면 끝이었다.
역시나 해결하고 나면 길이 조금은 보이는 것 같다.
매번 느끼는 문제는,
풀 때는 꽂힌 부분을 중심으로 고민하느라 문제를 넓은 시야로 보지 못한다는 것과 풀다보면 주변에서 금방 해결했다는 소식(?) 때문에 조바심이 나서 여유롭게 내 페이스와 논리대로 풀려고 집중하지 못한다는 것이다.
금방 고치긴 힘들겠지만, 아직 시간이 많은 만큼 끈기를 가지고 내 속도와 방식대로 풀 수 있도록 해봐야겠다.