카카오 블라인드 테스트 Solution · · 3 min read
[2019] 매칭 점수
문제 설명
- 한 웹페이지에 대해서 기본점수, 외부 링크 수, 링크점수, 매칭점수를 구할 수 있다.
- 기본점수 : 텍스트 중에 검색어가 등장한 횟수(대소문자 무시)
- 외부 링크 수 : 다른 외부 페이지로 연결된 링크의 개수
- 링크점수 : ( 해당 웹페이지로 걸린 다른 웹페이지의 기본점수 ) / ( 외부링크 수) 의 합
- 매칭점수 : 기본점수 + 링크점수
- 매칭점수가 높은 웹페이지의 번호를 리턴한다.
- 매칭점수가 같은 웹페이지가 여러 개라면 그중 번호가 가장 작은 것을 구한다.
입력 예시 :
["<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>#!MuziMuzi!)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>"]

검색어 : hi
- A의 기본점수 : 1점
- B의 기본점수 : 4점
- C의 기본점수 : 9점
외부 링크 수
- A : 1개
- B : 2개
- C : 3개
링크 점수
- A : ( 4 / 2 ) + ( 9 / 3 ) = 5점
- B : 0점
- C : 0점
매칭점수
- A : 6점
- B : 4점
- C : 9점
문제 풀이
- 입력 형식을 파싱하여 각 웹페이지의 URL과 링크 URL, index, 기본점수, (기본점수 / 링크수)를 구한다.
- 각 웹페이의 매칭점수를 완성하고, 매칭 점수를 기준으로하여 내림차순으로 정렬하여 매칭 점수가 가장 높은 웹페이지의 index를 리턴한다.
- &&는 왼쪽 것이 false라면 오른쪽 조건을 확인하지 않는다는 것을 이용한다.
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool is_alpha(char a)
{
if ('a' <= a && a <= 'z')
{
return true;
}
if ('A' <= a && a <= 'Z')
{
return true;
}
return false;
}
// <, >기준으로 문자열을 split한다.
vector<string> split_by_Opne_Close(string input)
{
vector<string> ret;
string tmp = "";
for (int i = 0; i < input.length(); i++)
{
if (input[i] == '<')
{
if (tmp != "\n" && tmp.length() != 0)
{
ret.push_back(tmp);
}
tmp = "<";
}
else if (input[i] == '>')
{
tmp += input[i];
ret.push_back(tmp);
tmp = "";
}
else
{
tmp += input[i];
}
}
return ret;
}
//알파벳이 아닌 것을 기준으로 split
vector<string> split_not_alphabet(string input)
{
vector<string> ret;
string tmp = "";
for (int i = 0; i < input.length(); i++)
{
if (is_alpha(input[i]))
{
tmp += tolower(input[i]);
}
else
{
if (tmp.length() != 0)
{
ret.push_back(tmp);
tmp = "";
}
}
}
return ret;
}
class Page
{
private:
int idx; //몇번째 인풋인지
double itlinkscore; //현재 페이지의 (기본점수 / 링크수)
double matchingscore; //현재 페이지의 매칭 스코어
string url; //현재 페이지의 URL
vector<string> link; //링크 url정보
public:
Page(int, string, string);
string getUrl()
{
return this->url;
}
double getItLinkScore()
{
return this->itlinkscore;
}
void addMatchingScore(double itlinkscore)
{
this->matchingscore += itlinkscore;
}
double getMatchinScore()
{
return this->matchingscore;
}
int getIdx()
{
return this->idx;
}
vector<string> getLink()
{
return this->link;
}
};
Page::Page(int idx, string word, string input)
{
this->idx = idx;
this->url = "";
vector<string> info = split_by_Opne_Close(input);
int i = 0;
//url을 찾는다
//<meta 를 찾는다 size가 27개 보다 많을 경우 체크한다
while (1)
{
if (27 < info[i].length())
{
//시작이 <meta이고
if (info[i][0] == '<' && info[i][1] == 'm' && info[i][2] == 'e' && info[i][3] == 't' && info[i][4] == 'a')
{
int j;
//중간에 content="https://"가 있다면
for (j = 5; j < info[i].length(); j++)
{
if (info[i][j] == 'c' && info[i][j + 1] == 'o' && info[i][j + 2] == 'n' && info[i][j + 3] == 't' && info[i][j + 4] == 'e' && info[i][j + 5] == 'n' && info[i][j + 6] == 't' && info[i][j + 7] == '=' && info[i][j + 8] == '\"' && info[i][j + 9] == 'h' && info[i][j + 10] == 't' && info[i][j + 11] == 't' && info[i][j + 12] == 'p' && info[i][j + 13] == 's' && info[i][j + 14] == ':' && info[i][j + 15] == '/' && info[i][j + 16] == '/')
{
for (int k = j + 17; info[i].length(); k++)
{
if (info[i][k] == '\"')
{
break;
}
this->url += info[i][k];
}
break;
}
}
if (this->url.length() != 0)
{
break;
}
}
}
i++;
}
//외부로의 링크를 추가한다.
for (i++; i < info.size(); i++)
{
//<a href="https:// 부터 "가 나올때까지의 url을 받아 외부링크를 완성한다.
if (info[i][0] == '<' && info[i][1] == 'a' && info[i][2] == ' ' && info[i][3] == 'h' && info[i][4] == 'r' && info[i][5] == 'e' && info[i][6] == 'f' && info[i][7] == '=' && info[i][8] == '\"' && info[i][9] == 'h' && info[i][10] == 't' && info[i][11] == 't' && info[i][12] == 'p' && info[i][13] == 's' && info[i][14] == ':' && info[i][15] == '/' && info[i][16] == '/')
{
string tmp = "";
for (int j = 17; j < info[i].length(); j++)
{
if (info[i][j] == '\"')
{
break;
}
tmp += info[i][j];
}
this->link.push_back(tmp);
}
}
int numberoflink = this->link.size();
info = split_not_alphabet(input);
int score = 0;
for (i = 0; i < info.size(); i++)
{
if (word == info[i])
{
score++;
}
}
this->matchingscore = score;
this->itlinkscore = (double)score / (double)numberoflink;
}
int solution(string word, vector<string> pages)
{
vector<Page> parsing_pages;
for (int i = 0; i < word.length(); i++)
{
word[i] = tolower(word[i]);
}
for (int i = 0; i < pages.size(); i++)
{
Page page(i, word, pages[i]);
parsing_pages.push_back(page);
}
//매칭점수를 완성시킨다.
for (int i = 0; i < pages.size(); i++)
{
vector<string> tmpLink = parsing_pages[i].getLink();
for (int j = 0; j < tmpLink.size(); j++)
{
for (int k = 0; k < pages.size(); k++)
{
if (tmpLink[j] == parsing_pages[k].getUrl())
{
parsing_pages[k].addMatchingScore(parsing_pages[i].getItLinkScore());
}
}
}
}
sort(parsing_pages.begin(), parsing_pages.end(), [](Page a, Page b)
{
if (a.getMatchinScore() == b.getMatchinScore())
{
return a.getIdx() < b.getIdx();
}
return b.getMatchinScore() < a.getMatchinScore();
}
);
return parsing_pages.front().getIdx();
}