본문 바로가기
Algorithm

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

by dokkisan 2023. 11. 25.

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

 

프로그래머스

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

programmers.co.kr

 

그동안 코딩 테스트 준비를 하지 않았지만, 취업 뿐 아니라 문제 해결 능력 향상을 비롯해 문법에 익숙해지기 위해 꾸준히 풀어보는 것이 좋을 것 같다.

이 문제는 2021 카카오 채용연계형 인턴십 기출 문제이다.

제출은 했지만 코드가 정말 지저분하다고 생각한다.. 심지어 1시간 동안 풀었다.

여러모로 반성을 하게 되는 문제였지만, 그래도 스스로 생각한 로직으로 풀어냈고 알고리즘에 대한 자신감을 회복해 기분이 좋다!

 

변수 s에 일부 영단어가 들어있는데, 이를 숫자로 변환해야 한다.

영단어와 간편하게 비교하고 숫자를 바로 꺼내올 수 있도록 Map을 사용했다.

아래는 처음 작성한 코드이다.

public static int solution(String s) {
		int answer = 0;

		Map<String, Integer> numbers = new HashMap<>();
		numbers.put("zero", 0);
		numbers.put("one", 1);
		numbers.put("two", 2);
		numbers.put("three", 3);
		numbers.put("four", 4);
		numbers.put("five", 5);
		numbers.put("six", 6);
		numbers.put("seven", 7);
		numbers.put("eight", 8);
		numbers.put("nine", 9);

		List<String> input = new ArrayList<>(Arrays.asList(s.split("")));
		List<String> word = new ArrayList<>();
		List<Integer> result = new ArrayList<>();
		for (int i = 0; i < input.size(); i++) {
			if (!input.get(i).matches("[0-9]")) {    // 영단어면
				if (numbers.containsKey(word.toString())) { // 저장해둔 영단어가 완성됐는지 확인
					result.add(numbers.get(word.toString()));
					word.clear();
				} else {
					word.add(input.get(i)); // 완성이 안 됐으면 영단어 저장
				}
			}
			result.add(Integer.parseInt(input.get(i))); // 숫자면 그대로 result에 저장
		}

		System.out.println(result);
		return answer;
	}

왜인지 result가 빈 리스트로 출력되었다.

아마 List<String> result에 toString()을 사용하면 문자열로 변환되지 않는 것 같다.

List 대신 StringBuilder를 사용하도록 수정했다.

public static int solution(String s) {
		int answer = 0;

		Map<String, Integer> numbers = new HashMap<>();
		numbers.put("zero", 0);
		numbers.put("one", 1);
		numbers.put("two", 2);
		numbers.put("three", 3);
		numbers.put("four", 4);
		numbers.put("five", 5);
		numbers.put("six", 6);
		numbers.put("seven", 7);
		numbers.put("eight", 8);
		numbers.put("nine", 9);

		List<String> input = new ArrayList<>(Arrays.asList(s.split("")));
		StringBuilder word = new StringBuilder();
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < input.size(); i++) {
			if (!input.get(i).matches("[0-9]")) {    // 영단어면
				if (numbers.containsKey(word.toString())) { // 저장해둔 영단어가 완성됐는지 확인
					result.append(numbers.get(word.toString()));
					word.setLength(0);
				}
				else {
					word.append(input.get(i)); // 완성이 안 됐으면 영단어 저장
					if (numbers.containsKey(word.toString())) { // 저장해둔 영단어가 완성됐는지 확인
						result.append(numbers.get(word.toString()));
						word.setLength(0);
					}
				}
			} else {
				result.append(Integer.parseInt(input.get(i))); // 숫자면 그대로 result에 저장
			}
		}

		answer = Integer.parseInt(result.toString());
		return answer;
	}

또 한가지 문제는 for문을 돌며 해당 인덱스에서 영단어가 완성되었음에도 다음 인덱스로 넘어갔다.

그렇다보니 이미 완성된 영단어를 삭제하고 다음 인덱스 부터 새로운 영단어를 만들어가다보니 최종적으로 result에는 변수 s에 이미 숫자로 들어왔던 값만 남게 되었다.

이를 해결하기 위해 다음 인덱스로 넘어가기 전, 문자를 word에 저장한 뒤 한 번 더 영단어가 완성됐는지 확인한다.

 

영단어가 완성되었는지 확인하는 조건문이 중복되고 있기 때문에, 상단에 있는 조건문은 삭제해도 될 것 같다.

 

이 문제를 풀면서 좀 더 공부해야 할 키워드를 얻을 수 있었다.

당연하게 사용해온 Integer.parseInt()Integer.valueOf()의 차이점에 대해 정확히 알지 못하고 있었다.

또 Integer.parseInt(result.toString())처럼, List에 저장된 숫자를 sum하지 않고 int 변수에 넣어주는 방법도 처음 고민해봤다.

지금 생각하면 정말 간단한 부분이지만 답을 모를 때에는 막막함이 먼저 드는 것 같다.

이 문제를 풀며 얻은 자신감을 통해 꾸준히 성장해나가야겠다!