코드로 문제 해결 연습 | 옹알이

주싱·2022년 12월 20일
0

링크 : 프로그래머스 > Level 0 > 옹알이

| 문제

머쓱이는 태어난 지 6개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음을 최대 한 번씩 사용해 조합한(이어 붙인) 발음밖에 하지 못합니다. 문자열 배열 babbling 이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.

| 주먹구구식 코드로 일단 해결

public class 옹알이 {
    @Test
    void tester() {
        int solution = solution(new String[]{"ayaye", "uuuma", "ye", "yemawoo", "ayaa"});
        Assertions.assertEquals(3, solution);
    }

    public int solution(String[] inputs) {
        int count = 0;

        for (String input : inputs) {
            int nextIndex = 0;
            while (true) {
                if (nextIndex >= input.length()) {
                    count++;
                    // 성공
                    break;
                }

                if ((nextIndex = scanWord(input, nextIndex)) == -1) {
                    // 실패
                    break;
                }
            }
        }
        return count;
    }

    private int scanWord(String input, int nextIndex) {
        List<String> speakableWords = List.of("aya", "ye", "woo", "ma");

        char firstChar = input.charAt(nextIndex);
        int i;
        for (i = 0; i<speakableWords.size(); i++) {
            String speakableWord = speakableWords.get(i);
            if (speakableWord.charAt(0) == firstChar) {
                if (input.length() < nextIndex + speakableWord.length()) {
                    nextIndex = -1;
                    break;
                }
                String substring = input.substring(nextIndex, nextIndex + speakableWord.length());
                if (speakableWord.equals(substring)) {
                    nextIndex += speakableWord.length();
                    break;
                }
            }
        }

        if (i == speakableWords.size()) {
            return -1;
        } else {
            return nextIndex;
        }
    }
}

| 선언적 코드로 개선

public class 옹알이 {
    @Test
    void tester() {
        int solution = solution(new String[]{"ayaye", "uuuma", "ye", "yemawoo", "ayaa"});
        Assertions.assertEquals(3, solution);
    }

    // 최종 해결책
    public int solution(String[] sentences) {
        return (int) Arrays.stream(sentences)
                                .filter(this::canSpeakSentence)
                                .count();
    }

    private boolean canSpeakSentence(String targetSentence) {
        String gettingCut = targetSentence;
        while (true) {
            String subSentence = gettingCut;
            // 문장이 말할 수 있는 발음으로 시작하는지 찾기
            Optional<String> startedWord = Stream.of("aya", "ye", "woo", "ma")
                                                   .filter(word -> started(subSentence, word))
                                                   .findAny();

            // 문장이 말할 수 있는 발음으로 시작하지 않는다면 문장을 말할 수 없습니다.
            if (startedWord.isEmpty()) {
                return false;
            }

            // 이어지는 문장이 발음 가능한지 검사하기 위해 찾아진 발음을 문장에서 제거
            gettingCut = gettingCut.substring(startedWord.get().length());
            if (gettingCut.isEmpty()) {
                return true;
            }
        }
    }

    boolean started(String targetSentence, String canSpeakWord) {
        if (targetSentence.length() < canSpeakWord.length()) {
            return false;
        }

        String targetSub = targetSentence.substring(0, canSpeakWord.length());
        return targetSub.equals(canSpeakWord);
    }

| 느낀점

For 문장의 복잡함

주먹구구식 코드를 작성하며 for 문의 흐름과 언제 break 로 분기해야 할지 전체 흐름이 한 눈에 파악되지 않아 어려웠고 불안한 마음이 들었다. Java의 Stream을 사용해 선언적으로 코드를 작성하다 보니 훨씬 코드 작성이 쉬워졌고 안정적인 마음이 들었다. 코드 가독성도 향상된 것 같다.

| 배운것

  • Stream 활용한 데이터 다루기 (filter, count)
  • 배열에서 Stream 생성하기 (Arrays.stream())
  • 각 요소에서 Stream 생성하기 (Stream.of())
  • 다시 한 번 기억하게 된다. String 객체는 불변성을 가진다.
profile
소프트웨어 엔지니어, 일상

0개의 댓글