일단 시작해보는 블로그

[알고리즘_풀이] 초성으로 노래가사 일치하는지 확인하기 본문

CS/알고리즘 풀이

[알고리즘_풀이] 초성으로 노래가사 일치하는지 확인하기

Selina Park 2019. 12. 3. 10:47

방탄소년단의 팬카페를 둘러보고 싶었는데 초성으로 노래를 찾아내라는 문제가 있었다. 

생각보다 구글링도 안되고 너무 어려워서 한번 구현해보자 생각을 했다.

 

class Main {
    public static void main(String[] args) {
        String lyric = "첫눈에 널 알아보게 됐어\n" +
                "서롤 불러왔던 것처럼\n" +
                "내 혈관 속 DNA가 말해 줘\n" +
                "내가 찾아 헤매던 너라는 걸\n" +
                "\n" +
                "우리 만남은 수학의 공식\n" +
                "종교의 율법 우주의 섭리\n" +
                "내게 주어진 운명의 증거\n" +
                "너는 내 꿈의 출처\n" +
                "Take it take it\n" +
                "너에게 내민 내 손은 정해진 숙명\n" +
                "\n" +
                "걱정하지 마 love\n" +
                "이 모든 건 우연이 아니니까\n" +
                "우린 완전 달라 baby\n" +
                "운명을 찾아낸 둘이니까\n" +
                "\n" +
                "우주가 생긴 그 날부터 계속\n" +
                "무한의 세기를 넘어서 계속\n" +
                "우린 전생에도 아마 다음 생에도\n" +
                "영원히 함께니까\n" +
                "\n" +
                "이 모든 건 우연이 아니니까\n" +
                "운명을 찾아낸 둘이니까\n" +
                "DNA\n" +
                "\n" +
                "I want it this love I want it real love\n" +
                "난 너에게만 집중해\n" +
                "좀 더 세게 날 이끄네\n" +
                "태초의 DNA가 널 원하는데\n" +
                "이건 필연이야 I love us\n" +
                "우리만이 true lovers\n" +
                "\n" +
                "그녀를 볼 때마다 소스라치게 놀라\n" +
                "신기하게 자꾸만 숨이 멎는 게 참 이상해 설마\n" +
                "이런 게 말로만 듣던 사랑이란 감정일까\n" +
                "애초부터 내 심장은 널 향해 뛰니까\n" +
                "\n" +
                "걱정하지 마 love\n" +
                "이 모든 건 우연이 아니니까\n" +
                "우린 완전 달라 baby\n" +
                "운명을 찾아낸 둘이니까\n" +
                "\n" +
                "우주가 생긴 그 날부터 계속\n" +
                "무한의 세기를 넘어서 계속\n" +
                "우린 전생에도 아마 다음 생에도\n" +
                "영원히 함께니까\n" +
                "\n" +
                "이 모든 건 우연이 아니니까\n" +
                "운명을 찾아낸 둘이니까\n" +
                "DNA\n" +
                "\n" +
                "돌아보지 말아\n" +
                "운명을 찾아낸 우리니까\n" +
                "후회하지 말아 baby\n" +
                "영원히\n" +
                "영원히\n" +
                "영원히\n" +
                "영원히\n" +
                "함께니까\n" +
                "\n" +
                "걱정하지 마 love\n" +
                "이 모든 건 우연이 아니니까\n" +
                "우린 완전 달라 baby\n" +
                "운명을 찾아낸 둘이니까\n" +
                "\n" +
                "La la la la la\n" +
                "La la la la la\n" +
                "우연이 아니니까\n" +
                "\n" +
                "La la la la la\n" +
                "La la la la la\n" +
                "우연이 아니니까";

		/* 노래를 전부 초성으로 바꾼다. */
        String str = getInitialOfLyric(lyric);

        System.out.println(searchSongForInitialWord("ㅇ ㅁㄷ ㄱ ㅇㅇㅇ ㅇㄴㄴㄲ", str));

    }

    // 1. 초성으로 바꾸기
    //  - getInitialOfLyric()
    //  - getInitialOfChar()
    public static String getInitialOfLyric(String lyric) {
        String[] lyric_list = lyric.split("\\n|\\s");
        String ret = "";

        for(String li : lyric_list) {
            for(int i=0; i<li.length(); i++) {
                String tmp = getInitialOfChar(li.charAt(i));
                ret += tmp;
            }
            ret += " ";
        }

        return ret;
    }

    // 한글 한글자를 초성으로 바꿔주는 메서드
    public static String getInitialOfChar(char c) {
        int first = (c - 44032 ) / ( 21 * 28 );
        String chosung = null;

        switch(first){
            case 0:
                chosung="ㄱ";
                break;
            case 1:
                chosung="ㄲ";
                break;
            case 2:
                chosung="ㄴ";
                break;
            case 3:
                chosung="ㄷ";
                break;
            case 4:
                chosung="ㄸ";
                break;
            case 5:
                chosung="ㄹ";
                break;
            case 6:
                chosung="ㅁ";
                break;
            case 7:
                chosung="ㅂ";
                break;
            case 8:
                chosung="ㅃ";
                break;
            case 9:
                chosung="ㅅ";
                break;
            case 10:
                chosung="ㅆ";
                break;
            case 11:
                chosung="ㅇ";
                break;
            case 12:
                chosung="ㅈ";
                break;
            case 13:
                chosung="ㅉ";
                break;
            case 14:
                chosung="ㅊ";
                break;
            case 15:
                chosung="ㅋ";
                break;
            case 16:
                chosung="ㅌ";
                break;
            case 17:
                chosung="ㅍ";
                break;
            case 18:
                chosung="ㅎ";
                break;
            default: chosung=String.valueOf(c);
        }


        return chosung;
    }


    // keyword와 일치하는지 확인하기
    public static boolean searchSongForInitialWord(String keyword, String lyric) {
        String[] keyword_list = keyword.split("\\s"); // keyword를 공백문자로 자른다.

        String tmp = "";
        if(lyric.indexOf(keyword_list[0]) == 0) {
            tmp = keyword_list[0];
        }else {
            tmp += " ";
            tmp += keyword_list[0];
        }

        boolean ret = lyric.contains(tmp); // 일단, keyword[0]과 일치하는게 있는지 확인한다.
        if(!ret) return false;

        // 여기부터는 lyric에 키워드가 포함되어있는데, keyword 덩아리(?) 자체가 한덩아리이면 그냥 true를 리턴한다.
        if(keyword_list.length == 1) return true;

        // 여기서부터는 keyword의 덩어리가 2개 이상이므로 keyword를 keyword_list[0](keyword의 첫번째 덩어리)로 잘라서 하나씩 확인해본다.
        String[] lyric_list = lyric.split(keyword_list[0]);

        for(int i=0; i<lyric_list.length; i++) {
            // 맞는게 하나라도 있으면 true 를 반환해야한다.
            if(isSameLyric(lyric_list[i], keyword_list)) {
                return true;
            }
        }

        return false;
    }



    // 첫번째 덩어리는 맞지만 뒤에도 모두 맞는지 확인하는 메서드
    public static boolean isSameLyric(String lyric, String[] keyword_list) {
        String[] str_list = lyric.split(" ");

        // keyword_list 기준으로 확인할 것이므로, str_list의 크기가 keyword_list보다 작으면 어쩌피 안맞는거니까 false
        if(str_list.length < keyword_list.length) return false;

        for(int i=1; i<keyword_list.length; i++) {
            if(keyword_list[i].equals(str_list[i])) {
                return true;
            }
        }

        return false;
    }
}
Comments