20231116_기록_숫자 문자열과 영단어(프로그래머스)

2023. 11. 16. 21:02IT/TIL

오늘 한 것들

 

알고리즘 코드카타

Chapter 2 프로그래밍기초 팀 프로젝트

 

오늘의 TIL은 숫자 문자열과 영단어로

문제의 내용은 1 <= s <= 50의 길이인 문자열로 주어지는 s가 있는데

이 s는 몇몇 숫자가 영단어로 변경되어 있는 경우가 있는데,

 

이 영단어로 변경된 문자열을 숫자로 변경하는 문제이다.

 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

예를들어

one4seveneight 라고 주어지면 1478로

23four5six7 라고 주어지면 234567로

1zerotwozero3 라고 주어지면 10203으로 변경되게하는 함수를 만드는 문제이다.

 

답으로 제출한 전체 코드는 아래와 같다.

더보기
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;

public class Solution {
    enum NumberWords
    {
        zero, one, two, three, four, five, six, seven, eight, nine
    }
    public int solution(string s) {
        int answer = 0;   
        
        List<string> newWordList = new List<string>();
        StringBuilder currentWord = new StringBuilder();

        for (int i = 0; i < s.Length; i++)
        {
            if (char.IsLetter(s[i]))
            {
                currentWord.Append(s[i]);
                if (Enum.TryParse<NumberWords>(currentWord.ToString(), out NumberWords numberWord))
                {
                    newWordList.Add(((int)numberWord).ToString());
                    currentWord.Clear();
                }
            }
            else if (char.IsDigit(s[i]))
            {
                newWordList.Add(s[i].ToString());
            }
        }

        string[] newWord = newWordList.ToArray();
        string result = string.Join("", newWord);
        answer = Int32.Parse(result);
        
        return answer;
    }
}

 

이 문제에서 사용한 방법 중 하나는 아래와 같이 정의한 enum인데

enum NumberWords
    {
        zero, one, two, three, four, five, six, seven, eight, nine
    }

 

위의 정의에 따라 zero를 0과 one을 1과, two를 2와 ... nine을 9와 연결시켰다.

 

이후에 List와 StringBuilder를 이용하여

    List<string> newWordList = new List<string>();
    StringBuilder currentWord = new StringBuilder();

    for (int i = 0; i < s.Length; i++)
    {
        if (char.IsLetter(s[i]))
        {
            currentWord.Append(s[i]);
            if (Enum.TryParse<NumberWords>(currentWord.ToString(), out NumberWords numberWord))
            {
                newWordList.Add(((int)numberWord).ToString());
                currentWord.Clear();
            }
        }
        else if (char.IsDigit(s[i]))
        {
            newWordList.Add(s[i].ToString());
        }
    }

 

주어진 문자열 s를 앞에서부터 읽어나가면서 끝까지 문자열인 경우,

현재까지의 문자열이 enum의 NumberWords와 비교해서 같은 값이 있다면

해당하는 숫자로 변환하여 리스트에 추가하고 지금까지 있었던 문자열을 지우게하고

해당하는 숫자가 없다면 계속해서 문자열을 추가하며 해당하는 숫자가 나타날 때까지 반복했다.

나타난 문자열이 숫자면 그대로 리스트에 추가시켰다.

 

예를들어 one4seveneight 이라는 문자열이 들어오면

s[0] = "o"
s[1] = "n"
s[2] = "e"
s[3] = "4", ...

이므로
currentWord는
처음에는 o가, 두번째에는 on이, 세번째에는 one이 되서 1로 newWordList에 추가되고
clear된다.
이후에 4가 들어오면 else if 문이 작동하 newWordList에 바로 4가 추가된다
그 이후엔 같은 방식으로
s, se, sev, seve, seven이 되는 순간 newWordList에 7이 추가되는 방식으로 작동한다.

 

이후 리스트로 작성한 newWordList를 string의 배열 newWord로 변환하고,

배열을 문자열로 합친 후에, 문자열을 정수로 변환하는 과정으로 답을 반환했다.

	string[] newWord = newWordList.ToArray();
        string result = string.Join("", newWord);
        answer = Int32.Parse(result);
        
        return answer;

 

 

처음에 이 문제를 접했을 때는 숫자와 문자열을 모두 잘라낸 다음,

문자열을 숫자로 변환하고, 변환되지 않으면 다시 문자열을 자르는
재귀 방식의 해결법을 사용하려고 했었으나,

해당 방법은 사람들은 단어를 잘라낼 수 있는 능력이 있어서 쉽게 할 수 있지만,
컴퓨터는 그런식으로 단어를 기억하고 있지 않기에 사용하기 어려운 방법이였다.
따라서 생각해낸 방법은 처음부터 시작해서 해당하는 문자열이 나오면 숫자로 변환하는
0번 인덱스부터 끝까지 순차적으로 진행하며 변환된 숫자를 새로운 문자열로 만드는 것이었다.
그 과정에서 Add함수를 사용하기 위해 List를 도입하였다.