ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스] 매칭 점수 (2019 KAKAO BLIND RECRUITMENT)
    ALGORITHM/PROGRAMMERS 2021. 3. 29. 21:38

    programmers.co.kr/learn/courses/30/lessons/42893

     

    코딩테스트 연습 - 매칭 점수

    매칭 점수 프렌즈 대학교 조교였던 제이지는 허드렛일만 시키는 네오 학과장님의 마수에서 벗어나, 카카오에 입사하게 되었다. 평소에 관심있어하던 검색에 마침 결원이 발생하여, 검색개발팀

    programmers.co.kr

    2021-03-29


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    import java.util.*;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
     
    public class Solution42893 {
        static class Link {
            int index;
            int base;
            int out;
            double linked;
     
            public Link(int index, int base, int outdouble linked) {
                this.index = index;
                this.base = base;
                this.out = out;
                this.linked = linked;
            }
        }
     
        public static String extractBody(String word) { // body 추출
            Pattern bodyPt = Pattern.compile("<body>(?s)(.*)</body>"); // <body>와 </body> 태그 사이에 있는 문장 추출
            Matcher bodyMat = bodyPt.matcher(word);
            String body = "";
            if (bodyMat.find()) {
                body = bodyMat.group(1);
            }
            return body;
        }
     
        public static int solution(String word, String[] pages) {
            int answer = 987654321;
            word = word.toLowerCase();
            HashMap<String, Link> map = new HashMap<>();
            String[] names = new String[pages.length];
     
            for (int i = 0; i < pages.length; i++) {
                // url 추출
                Pattern urlPt = Pattern.compile("<meta property=\"og:url\" content=\"https://(\\S*)\""); // url extract
                Matcher urlMat = urlPt.matcher(pages[i]);
                String url = "";
                if (urlMat.find()) {
                    url = urlMat.group(1);
                }
                // body 부분 추출
                String body = extractBody(pages[i]);
                // 외부 링크 수 count
                Pattern aPt = Pattern.compile("<a href="); // <a href= 개수
                Matcher aMat = aPt.matcher(body);
                int aCnt = 0;
                while (aMat.find()) {
                    aCnt++;
                }
                // 검색어 등장 횟수
                body = body.toLowerCase();
                int srchCnt = 0;
                int index = 0;
                while (true) {
                    index = body.indexOf(word, index + 1);
                    if (index < 0break;
                    char prev = body.charAt(index - 1);
                    char post = body.charAt(index + word.length());
                    if (!Character.isLetter(prev) && !Character.isLetter(post)) { // 양쪽 모두 글자가 아니어야함
                        srchCnt++;
                    }
                }
                map.put(url, new Link(i, srchCnt, aCnt, 0.0));
                names[i] = url;
            }
     
            for (int i = 0; i < pages.length; i++) {
                String body = extractBody(pages[i]);
                // 링크 점수
                Pattern aPt = Pattern.compile("<a href=\"https://(\\S*)\""); // <a href= 링크 개수
                Matcher aMat = aPt.matcher(body);
                String aUrl = "";
                while (aMat.find()) {
                    aUrl = aMat.group(1);
                    Link origin = map.get(names[i]);
                    if (map.get(aUrl) != null && origin.base != 0 && origin.out != 0) {
                        double link = (double) origin.base / (double) origin.out;
                        Link tmp = map.get(aUrl);
                        tmp.linked += link;
                        map.put(aUrl, tmp);
                    }
                }
            }
     
            //큰 매칭 값 찾기
            Iterator<String> keys = map.keySet().iterator();
            double value = 0.0;
     
            while (keys.hasNext()) {
                String next = keys.next();
                double matching = map.get(next).base + map.get(next).linked;
                if (value <= matching) {
                    if (value == matching) answer = Math.min(answer, map.get(next).index);
                    else answer = map.get(next).index;
                    value = matching;
                }
            }
     
            return answer;
        }
     
        public static void main(String[] args) {
    //        String w = "blind";
    //        String[] p = {"<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta property=\"og:url\" content=\"https://a.com\"/>\n</head>  \n<body>\nBlind@blINd Lorem Blind ipsum dolor Blind test sit amet, consectetur adipiscing elit. \n<a href=\"https://b.com\"> Link to b </a>\n</body>\n</html>"
    //                , "<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta property=\"og:url\" content=\"https://b.com\"/>\n</head>  \n<body>\nSuspendisblINdse potenti. Vivamus venenatis tellus non turpis bibendum, \neiei<a href=\"https://a.com\"> Link to a Blind </a>\nblind sed congue urna varius. Suspendisse feugiat nisl ligula, quis malesuada felis hendrerit ut.\n<a href=\"https://c.com\"> Link to c </a>\n</body>\n</html>"
    //                , "<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta property=\"og:url\" content=\"https://c.com\"/>\n</head>  \n<body>\nUt condimentum urna at felis sodales rutrum. Sed dapibus cursus diam, non interdum nulla tempor nec. Phasellus rutrum enim at orci consectetu blind\n<a href=\"https://a.com\"> Link to a </a>\n</body>\n</html>"};
            String w = "Muzi";
            String[] p = {"<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta property=\"og:url\" content=\"https://careers.kakao.com/interview/list\"/>\n</head>  \n<body>\n<a href=\"https://programmers.co.kr/learn/courses/4673\"></a>#!0muzi0muzi0!)jayg07con&&\n\n</body>\n</html>""<html lang=\"ko\" xml:lang=\"ko\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta property=\"og:url\" content=\"https://www.kakaocorp.com\"/>\n</head>  \n<body>\ncon%\tmuzI92apeach&2<a href=\"https://hashcode.co.kr/tos\"></a>\n\n\t^\n</body>\n</html>"};
            System.out.println(solution(w, p));
        }
    }
     
    cs

    #문제풀이

     

    생각보다 되게 오래 걸렸었던 문제이다. 그만큼 코드도 깔끔하지는 못하다,,, 

     

    1. line 38 ~ : url 추출하는 패턴을 사용했다. 맨처음 key값이 될 수 있는 url을 추출하였다. <meta ~ 로 시작하여 content 안에 있는 글자를 추출하였다. 

     

    2. line 45 ~ + extractBody() : body 부분을 추출했다. <body></body> 사이를 추출했다. 나중에 한 번 더 사용하려고 따로 빼서 사용했다. 

     

    3. line 47 ~  : 외부 링크 수를 count 했다. 단순히 <a href=로 시작하는 것의 개수를 세었다. (외부 링크 수 : 현재 페이지에서 외부로 연결된 링크 수)

     

    4. line 54 ~ : lowercase로 바꾼 후 검색어 등장 횟수를 체크했다. 찾고자 하는 word의 index를 찾은 후 그 word index의 앞word index + word.length의 뒤를 살펴 보았을 때 둘 다 글자가 아닌 경우 완벽하게 한 단어로 추출 할 수 있는 것이므로, 이 조건을 만족한 경우 수를 세주었다. (기본점수 : 찾고자 하는 글자 수)

     

    5. 위에 1~4번을 이용해서 url key 값을 뽑아내었고, 기본점수, 외부 링크 수를 계산하여 value값에 넣었다.

     

    6. line 70 ~ : body를 다시 한 번 추출해서, <a href=의 링크를 뽑아내었다. 위에서 key 값을 모두 뽑아내었으므로, 뽑아낸 링크가 key값에 존재하는 경우 그리고 기본 점수와 외부 링크 수가 0이 아닌 경우 링크 점수를 계산해주고 map에 추가해주었다. (링크 점수 : 다른 웹 페이지에서 해당 웹페이지로 외부 링크가 걸렸을 때, 그 다른 웹페이지의 기본점수 / 외부 링크 수)

     

    7. line 89~ : 만들어놓은 map을 돌면서 매칭 점수(기본 점수 + 링크 점수)를 계산 해주었다. index 값을 애초에 들고 다녔으므로 그냥 단순하게 index 값도 매칭점수 값 비교할 때 함께 비교했다.

    댓글

Programming Diary