숫자 문자열과 영단어
문제 설명
네오와 프로도는 재미있는 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때, 일부 자릿수를 영단어로 바꾼 카드를 건네줍니다. 프로도는 이 영단어를 기반으로 원래 숫자를 찾는 게임을 하게 됩니다.
예를 들어, 다음과 같은 변환이 이루어질 수 있습니다:
1478
→"one4seveneight"
234567
→"23four5six7"
10203
→"1zerotwozero3"
이와 같이 숫자의 일부 자릿수가 영단어로 바뀌거나, 바뀌지 않고 그대로인 문자열 s
가 주어졌을 때, 이 문자열이 의미하는 원래 숫자를 반환하는 함수를 작성해야 합니다.
영단어와 숫자의 매핑
아래는 숫자와 영단어 간의 매핑 테이블입니다.
숫자 | 영단어 |
---|---|
0 | zero |
1 | one |
2 | two |
3 | three |
4 | four |
5 | five |
6 | six |
7 | seven |
8 | eight |
9 | nine |
제한 사항
1 ≤ s의 길이 ≤ 50
s
가"zero"
또는"0"
으로 시작하는 경우는 주어지지 않습니다.- 반환 값이
1 이상 2,000,000,000 이하의 정수
가 되는 올바른 입력만s
로 주어집니다.
입출력 예시
s | result |
---|---|
"one4seveneight" |
1478 |
"23four5six7" |
234567 |
"2three45sixseven" |
234567 |
"123" |
123 |
- 입출력 예 #1: 문제 예시와 같습니다.
- 입출력 예 #2:
"23four5six7"
에서 "four"와 "six"가 각각 4와 6에 해당하여, 결과는 234567입니다. - 입출력 예 #3: "three"는 3, "six"는 6, "seven"은 7에 대응되기 때문에 결과는 234567입니다.
- 입출력 예 #4:
s
에는 영단어로 바뀐 부분이 없습니다.
알고리즘 구현
아래는 Java로 작성된 해결 방법입니다. 이 코드는 문자열을 읽어들여 각 자릿수가 영단어인지 아닌지를 판단하여 원래 숫자로 변환합니다.
내가 구현한 코드
import java.util.Map;
public class Solution {
static Map<String, Integer> DIGIT_MAP = Map.of(
"zero", 0,
"one", 1,
"two", 2,
"three", 3,
"four", 4,
"five", 5,
"six", 6,
"seven", 7,
"eight", 8,
"nine", 9
);
public int solution(String s) {
// 입력된 문자열 s의 각 인덱스의 char가 digit인지 아닌지 판단.
// 만약 DIGIT (o) - StringBuilder - result에 문자를 더한다.
// 만약 DIGIT (x) -
// 임시 StringBuilder tmp를 만들어서 크기가 (3~5)가 될 경우 Map안의 키와 비교
// 매칭 될 경우 해당 키를 result에 더한다.
// 매칭 되지 않을 경우 tmp에 char를 더한다.
//
StringBuilder result = new StringBuilder();
StringBuilder tmpDigit = new StringBuilder();
for(char c : s.toCharArray()) {
if(Character.isDigit(c)){
result.append(c);
tmpDigit.setLength(0);
}else{
// 단순 캐릭터
if(DIGIT_MAP.get(tmpDigit.toString()) != null){
result.append(DIGIT_MAP.get(tmpDigit.toString()));
tmpDigit.setLength(0);
}else{
tmpDigit.append(c);
if(tmpDigit.length() >= 3 && tmpDigit.length() <= 5 && DIGIT_MAP.get(tmpDigit.toString()) != null){
result.append(DIGIT_MAP.get(tmpDigit.toString()));
tmpDigit.setLength(0);
}
}
}
}
return Integer.valueOf(result.toString());
}
}
최적화 코드
package lv1.숫자문자열과영단어;
import java.util.Map;
public class Solution {
static Map<String, Integer> DIGIT_MAP = Map.of(
"zero", 0,
"one", 1,
"two", 2,
"three", 3,
"four", 4,
"five", 5,
"six", 6,
"seven", 7,
"eight", 8,
"nine", 9
);
public int solution(String s) {
StringBuilder result = new StringBuilder();
StringBuilder tmpDigit = new StringBuilder();
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) {
result.append(c);
tmpDigit.setLength(0); // 숫자일 경우 tmpDigit 초기화
} else {
tmpDigit.append(c);
// tmpDigit의 길이가 3~5일 때 매칭 체크
if (tmpDigit.length() >= 3 && tmpDigit.length() <= 5) {
String key = tmpDigit.toString();
if (DIGIT_MAP.containsKey(key)) {
result.append(DIGIT_MAP.get(key));
tmpDigit.setLength(0); // 매칭 후 초기화
}
}
}
}
// 남아 있는 tmpDigit 확인
if (tmpDigit.length() > 0 && DIGIT_MAP.containsKey(tmpDigit.toString())) {
result.append(DIGIT_MAP.get(tmpDigit.toString()));
}
return Integer.parseInt(result.toString()); // 결과를 정수로 변환하여 반환
}
public static void main(String[] args) {
Solution main = new Solution();
System.out.println(main.solution("one4seveneight")); // 출력: 1478
}
}
코드 설명
- 맵 초기화: 숫자와 영단어 간의 관계를 정의한
DIGIT_MAP
을 생성합니다. - 문자열 순회: 입력된 문자열의 각 문자를 순회하면서, 숫자인 경우에는 결과에 추가하고, 영단어인 경우에는
tmpDigit
에 추가합니다. - 영단어 체크:
tmpDigit
의 길이가 3~5일 경우, 해당 영단어가DIGIT_MAP
에 존재하는지 확인하여 매칭이 된다면 결과에 추가합니다. - 최종 결과: 모든 문자를 처리한 후,
tmpDigit
에 남아 있는 영단어도 체크하여 결과에 추가합니다.
이 알고리즘을 통해 주어진 문자열을 원래 숫자로 효과적으로 변환할 수 있습니다. 이제 여러분도 이 문제를 해결할 수 있는 능력을 갖추었습니다!
이 글이 도움이 되기를 바랍니다. 추가적인 질문이나 수정이 필요하면 말씀해 주세요!
'여러가지 > 알고리즘 & 자료구조' 카테고리의 다른 글
[프로그래머스] 푸드 파이트 대회 (1) | 2024.10.16 |
---|---|
[프로그래머스] k번째수 (0) | 2024.10.16 |
[프로그래머스] 가장 가까운 같은 글자 (0) | 2024.10.16 |
[프로그래머스] 시저암호 (0) | 2024.10.16 |
[프로그래머스] 핸드폰 번호 가리기 (0) | 2024.10.14 |