오늘날 세계 대부분의 사람들은 아라비아 숫자(0–9)를 사용해요. 하지만 2천 년 전으로 거슬러 올라가 보면, 대부분의 유럽인들은 그 대신 로마 숫자를 사용하고 있었을 거예요.
로마 숫자를 쓰려면 다음과 같은 라틴 문자를 사용하는데, 각 문자에는 값이 있어요:
| M | D | C | L | X | V | I |
|---|---|---|---|---|---|---|
| 1000 | 500 | 100 | 50 | 10 | 5 | 1 |
로마 숫자는 이러한 문자를 나열한 것이고, 그 값은 각 문자가 가진 값의 합이에요.
예를 들어 XVIII의 값은 18이에요(10 + 5 + 1 + 1 + 1 = 18).
그런데 상황을 더 까다롭게 만드는 규칙이 하나 있어요. 바로 같은 문자를 연달아 세 번 넘게 사용할 수 없다는 점이에요.
그래서 4 같은 숫자는 겉보기에 자연스러워 보이는 IIII로 나타낼 수 없어요.
대신 그런 숫자에는 두 문자 사이의 뺄셈 방식을 사용해요.
즉, 4를 1 + 1 + 1 + 1이 아니라 5 - 1로 생각하는 거예요.
그리고 현대적인 사고방식에서는 조금 헷갈리게도, 더 작은 숫자를 먼저 써요.
이 방식은 다음 경우에만 적용돼요: 4(IV), 9(IX), 40(XL), 90(XC), 400(CD), 900(CM).
로마 숫자에서는 순서가 중요해요! 문자(그리고 위의 특별한 조합)는 왼쪽에서 오른쪽으로 값이 작아지는 순서로 배열해야 해요.
몇 가지 예를 살펴봐요:
105 => CV
---- => --
100 => C
+ 5 => V
106 => CVI
---- => --
100 => C
+ 5 => V
+ 1 => I
104 => CIV
---- => ---
100 => C
+ 4 => IV
그리고 마지막으로 좀 더 복잡한 예예요:
1996 => MCMXCVI
----- => -------
1000 => M
+ 900 => CM
+ 90 => XC
+ 5 => V
+ 1 => I
이번 과제는 아라비아 숫자를 로마 숫자로 변환하는 거예요.
이 연습 문제에서는 전통적인 로마 숫자만 다뤄요. 전통적인 로마 숫자에서 가장 큰 수는 MMMCMXCIX(또는 3,999)예요.
아라비아 숫자와 로마 숫자를 변환하는 방법은 아주 많아요. 먼저 단순한 방식으로 로마 숫자의 개념에 익숙해진 다음, 더 효율적인 방법을 찾아보는 걸 추천해요.
어떤 접근법을 쓸 수 있는지 알아보고 싶다면, 마지막에 있는 Deep Dive 영상도 꼭 확인해 봐요!
조금 색다른 걸 원한다면 unfold 함수를 사용한 풀이도 시도해 볼 수 있어요.
아마 foldLeft/Right는 이미 익숙할 거예요: 컬렉션 전체를 다른 것(보통 컬렉션이 아닌 것)으로 "매핑"하는 거죠.
unfoldLeft/Right는 "역" 연산이에요: 뭔가(보통 컬렉션이 아닌 것)를 컬렉션으로 "매핑"하는 거죠.
따라서 unfold하는 것은 함수형 프로그래밍(FP) 표준 레퍼토리에 논리적으로 추가되는 것이고, 그 일부이기도 해요.
이 연습 문제는 unfold하는 사례로 볼 수 있어요: Int를 String으로 "매핑"하는 거죠. (String은 물론 암시적으로 Seq[Char]예요.)
안타깝게도 unfoldLeft/Right는 Scala의 컬렉션 라이브러리에 포함되어 있지 않아요.
하지만 여기에서 구현을 가져올 수 있어요.