본문 바로가기

알고리즘/PROGRAMMERS

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

2021 카카오 채용연계형 인턴십 문제
2021 카카오 채용연계형 인턴십 문제
2021 카카오 채용연계형 인턴십 문제

 

알고리즘)

영문자로 입력되는 숫자를 해당하는 숫자로 대체시키는 문제입니다.

String형태여서 한 문자씩 읽을 수 있기 때문에 문자가 숫자인 경우와 영문자인 경우로 나눠서 코딩했습니다.

 

먼저 한 문자씩 읽어야 하므로 아래와 같이 String의 charAt() 메소드를 활용했습니다.

String s = "2three45sixseven"
int idx = 0;
System.out.println(s.charAt(idx));	// 2

 

읽어들인 문자가 숫자인 경우는 바로 결과값에 더해주기만 하면 됩니다.

반대로 영문자인 경우는 숫자로 변환해주고 결과값에 반영해야 되기 때문에 HashMap을 활용했습니다.

// 영어단어를 숫자로 매핑
Map<String, String>numWord = new HashMap<>();
numWord.put("zero", "0");
numWord.put("one", "1");
numWord.put("two", "2");
numWord.put("three", "3");
numWord.put("four", "4");
numWord.put("five", "5");
numWord.put("six", "6");
numWord.put("seven", "7");
numWord.put("eight", "8");
numWord.put("nine", "9");

 

여기서 알파벳 'z'를 읽었다면 영어단어 "zero"임이 분명하므로 "0"으로 maping해서 결과값에 반영합니다.

만약 알파벳 't'를 읽었다면 "two"와 "three"로 2가지의 경우가 발생합니다.

String의 substring() 메소드를 사용해서 이들을 구별하기로 했습니다.

String s = "2three45sixseven";
int start_idx = 1;
int end_idx = 5;
System.out.println(s.substring(start_idx, end_idx))	// "three"

 

단어별로 시작하는 알파벳에 맞춰 switch case문을 작성해서 위의 동작들은 반복 수행했습니다.

 

첫 번째 시도)

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class NumberWord {
    public static void main(String[] args){
        String s = "2three45sixseven";
        // 영어단어를 숫자로 매핑
        Map<String, String>numWord = new HashMap<>();
        numWord.put("zero", "0");
        numWord.put("one", "1");
        numWord.put("two", "2");
        numWord.put("three", "3");
        numWord.put("four", "4");
        numWord.put("five", "5");
        numWord.put("six", "6");
        numWord.put("seven", "7");
        numWord.put("eight", "8");
        numWord.put("nine", "9");
        // 숫자인지 아닌지 확인하는 패턴
        String pattern = "^[0-9]*$";
        String answer = "";
        
        // 숫자면 한 글자씩, 영단어면 case별로 동작
        for(int idx= 0; idx < s.length();) {

            if(Pattern.matches(pattern, s.substring(idx, idx+1))) {
                answer += s.charAt(idx);
                idx++;
            }
            else {
                switch(s.charAt(idx)){
                    case'z':
                        answer += numWord.get(s.substring(idx,idx+4));
                        idx+=4;
                        break;
                    case'o':
                        answer += numWord.get(s.substring(idx,idx+3));
                        idx+=3;
                        break;
                    case't':
                        if(s.substring(idx, idx+3).equals("two")) {
                            answer += numWord.get(s.substring(idx,idx+3));
                            idx += 3;
                        } else {
                            answer += numWord.get(s.substring(idx,idx+5));
                            idx += 5;
                        }
                        break;
                    case'f':
                        answer += numWord.get(s.substring(idx, idx + 4));
                        idx += 4;
                        break;
                    case's':
                        if(s.substring(idx,idx+3).equals("six")) {
                            answer += numWord.get(s.substring(idx, idx + 3));
                            idx += 3;
                        } else {
                            answer += numWord.get(s.substring(idx, idx + 5));
                            idx+=5;
                        }
                        break;
                    case'e':
                        answer += numWord.get(s.substring(idx, idx + 5));
                        idx += 5;
                        break;
                    case'n':
                        answer += numWord.get(s.substring(idx,idx+4));
                        idx+=4;
                        break;
                }
            }
        }
        System.out.println("answer : " + answer);
        int num = Integer.parseInt(answer);
    }
}

 

아래의 결과처럼 정상적으로 동작하는 것을 확인했습니다.

 

 

작성한 코드를 훑어보다 문득 "Java 치고 너무 딱딱하다"는 생각이 들었습니다.

 

영문자를 하나씩 읽어내려 간다는 점,

switch case문을 사용해서 쓸데없이 코드가 간결하지 못한 점,

숫자인지 알파벳인지 확인하기 위해 굳이 점화식을 사용해야 했을까 하는 점 등이 원인이었습니다.

 

그래서 다른 사람의 코드를 살펴봤는데 간결하고, 이해하기도 쉬워서 코드를 첨부하려 합니다.

아래의 코드는 프로그래머스의 '다른 사람의 풀이' 페이지 최상단에 있는 코드입니다.

 

jun7xxx님, 코x바님, 김x호님의 코드)

import java.util.*;

class Solution {
    public int solution(String s) {
        int answer = 0;
        StringBuilder sb = new StringBuilder("");
        int len = s.length();
        String[] digits = {"0","1","2","3","4","5","6","7","8","9"};
        String[] alphabets = {"zero","one","two","three","four","five","six","seven","eight","nine"};

        for(int i=0; i<10; i++){
            s = s.replaceAll(alphabets[i],digits[i]);
        }

        return Integer.parseInt(s);
    }
}

 

String의 replaceAll() 메소드를 사용해서 쉽게 변환되는 코드가 매우 인상 깊었습니다.

 

※ 문제 링크

- https://programmers.co.kr/learn/courses/30/lessons/81301

 

코딩테스트 연습 - 숫자 문자열과 영단어

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다. 다음은 숫자의 일부 자

programmers.co.kr