Algorithm/programmers

[2019 카카오 블라인드]매칭 점수

마닐라 2022. 7. 15. 14:33

📍 문제 설명

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

 

프로그래머스

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

programmers.co.kr

 

💡 접근

문자열 파싱을 알맞게 잘 할 수 있는지 물어볼 수 있는 문제였다.

indexOf를 이용해서 각 태그들에 대해서 필요한 문자열을 추출한다.

1. <meta> 태그 안에 있는 웹페이지 URL -> <meta> 태그는 여러개일 수 있다.

2. <body> 태그 안에 있는 검색어

3. <body> 태그 안에 있는 <a href> 태그 URL

 

링크점수는 기본점수 / 외부링크 수 이므로 계산이 가능하고 매칭 점수에 더해지므로 따로 관리 안해도 된다.

페이지의 인덱스, 기본 점수, 외부 링크 수, 매칭 점수를 저장하면 원하는 답을 찾을 수 있다.

 

👩‍💻 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

class Main {
    class Page implements Comparable<Page> {
        private int idx;
        private int searchScore, linkCnt;
        double score;

        public Page(int idx, int searchScore, int linkCnt, double score) {
            this.idx = idx;
            this.searchScore = searchScore;
            this.linkCnt = linkCnt;
            this.score = score;
        }

        @Override
        public int compareTo(Page o) {
            if(this.score == o.score) return this.idx - o.idx;
            else if(this.score < o.score) return 1;
            else return -1;
        }
    }

    public int solution(String word, String[] pages) {
        int answer = 0;
        //기본점수, 외부 링크 수, 링크점수(다른 웹페이지 기본점수 % 외부 링크 수), 매칭점수(기본+링크)
        //기본점수 -> body 태그 안에서 키워드를 찾자. (양 옆이 문자가 아니어야함)
        //링크점수 -> body 태그 안에서 <a href= ~ 링크를 찾자. + 어디에 기록해놔야함

        //링크 점수를 구하기 위해서 <url, index> 형식으로 저장
        Map<String, Integer> map = new HashMap<>();
        //각 웹페이지의 점수 관리
        List<Page> pageList = new ArrayList<>();

        word = word.toLowerCase();
        //페이지 별로 구할 수 있는 점수 구하기
        for(int i = 0; i < pages.length; i++) {
            String s = pages[i] = pages[i].toLowerCase();
            //meta 태그 내에 웹페이지 URL 구하기
            int mid = 0, posl = 0, posr = 0;
            //meta 태그가 여러 개 일 수 있다. 
            while (mid <= posl) {
                posl = s.indexOf("<meta", posl + 1);
                posr = s.indexOf(">", posl);
                mid = s.lastIndexOf("https://", posr);
            }
            posr = s.indexOf("\"", mid);
            String url = s.substring(mid, posr);

            int wordLen = word.length();
            //body 태그 내에 검색어 등장 횟수 구하기
            posl = s.indexOf("<body>", posr);
           int searchScore = 0;
            for(int start = posl; ;) {
                start = s.indexOf(word, start + 1);
                if (start == -1) break;
                //검색어의 앞뒤가 문자가 아니어야 검색어로 인정한다.
                if (!Character.isLetter(s.charAt(start-1)) && !Character.isLetter(s.charAt(start+ wordLen))) {
                    searchScore += 1;
                    start += wordLen;
                }
            }

            //body 태그 내에 하이퍼링크 갯수 구하기
            int linkCnt = 0;
            for(int start = posl; ;) {
                start = s.indexOf("<a href", start + 1);
                if (start == -1) break;
                linkCnt++;
            }

            //링크 점수를 구하기 위해서 저장
            map.put(url, i);
            //페이지의 인덱스, 기본점수, 외부 링크 수 , 매칭점수 저장
            pageList.add(new Page(i, searchScore, linkCnt, searchScore));
        }

        //위의 작업이 끝나고 map에 페이지들이 담겨야 list에 담긴 링크 점수를 갱신할 수 있음
        //링크 점수 구하기
        for(int i = 0; i < pages.length; i++) {
            String s = pages[i];
            for(int posl = 0, posr = 0; ;) {
                posl = s.indexOf("<a href", posr);
                //하이퍼링크 없으면 끝내기
                if(posl == -1) break;

                posl = s.indexOf("https://", posl);
                posr = s.indexOf("\"", posl);
                String linkurl = s.substring(posl, posr);
                //map에 linkurl이 있는지 확인하고 점수 더해주기(기본 점수는 이미 더해놨으니 링크점수 누적해서 더하기)
                Integer value = map.get(linkurl);
                if(value != null) {
                    pageList.get(value).score += (double)pageList.get(i).searchScore / pageList.get(i).linkCnt;
                }
            }
        }
        Collections.sort(pageList);
        answer = pageList.get(0).idx;
       return answer;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Main main = new Main();

        String word = "blind";
        String[] pages = {"<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>\n" +
                "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>\n" +
                        "Suspendisse potenti. Vivamus venenatis tellus non turpis bibendum, \n" +
                        "<a href=\"https://a.com\"> Link to a </a>\n" +
                        "blind 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>\n" +
                "Ut 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>"};
        main.solution(word, pages);
    }
}