여러가지/알고리즘 & 자료구조

[프로그래머스] 숫자 문자열과 영단어

hyeseong-dev 2024. 10. 16. 15:23

숫자 문자열과 영단어

문제 설명

네오와 프로도는 재미있는 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때, 일부 자릿수를 영단어로 바꾼 카드를 건네줍니다. 프로도는 이 영단어를 기반으로 원래 숫자를 찾는 게임을 하게 됩니다.

예를 들어, 다음과 같은 변환이 이루어질 수 있습니다:

  • 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
    }
}

코드 설명

  1. 맵 초기화: 숫자와 영단어 간의 관계를 정의한 DIGIT_MAP을 생성합니다.
  2. 문자열 순회: 입력된 문자열의 각 문자를 순회하면서, 숫자인 경우에는 결과에 추가하고, 영단어인 경우에는 tmpDigit에 추가합니다.
  3. 영단어 체크: tmpDigit의 길이가 3~5일 경우, 해당 영단어가 DIGIT_MAP에 존재하는지 확인하여 매칭이 된다면 결과에 추가합니다.
  4. 최종 결과: 모든 문자를 처리한 후, tmpDigit에 남아 있는 영단어도 체크하여 결과에 추가합니다.

이 알고리즘을 통해 주어진 문자열을 원래 숫자로 효과적으로 변환할 수 있습니다. 이제 여러분도 이 문제를 해결할 수 있는 능력을 갖추었습니다!


이 글이 도움이 되기를 바랍니다. 추가적인 질문이나 수정이 필요하면 말씀해 주세요!