[프로그래머스] 매칭 점수

박형진·2022년 3월 18일
0

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


import re
from collections import defaultdict
# 1. 본인링크 획득 -> domain[a.com] = [idx, 총점]
# 2. 외부링크 = [...], 기본 점수 = x
# 3. domain[a.com][1] += x
# 4. 링크점수 = 기본점수 // len(외부링크)
# 5. domain[외부링크][1] += 링크점수

def solution(word, pages):
    # [idx, 총점]
    domain = defaultdict(lambda: [999, 0.0])
    for idx, page in enumerate(pages):
        # 모든 문자 대문자로 통일
        upper_page = page.upper()
        # 본인링크 탐색(=domain[name])
        start_idx = upper_page.find('<META PROPERTY="OG:URL" CONTENT="HTTPS://')
        name = ''
        for i in range(start_idx + 41, len(upper_page)):
            if upper_page[i] == '\"':
                break
            name += upper_page[i]
        # 외부 링크 탐색
        outer_link = []
        find_start = 0
        while True:
            outer = ''
            start_idx = upper_page.find('<A HREF="HTTPS://', find_start)
            if start_idx == -1:
                break
            for i in range(start_idx + 17, len(upper_page)):
                if upper_page[i] == '\"':
                    find_start = i + 1
                    break
                outer += upper_page[i]
            outer_link.append(outer)
        # 기본 점수 계산(word 찾기)
        # 문제 설명: 단어는 알파벳을 제외한 다른 모든 문자로 구분한다.
        count = 0
        for e in re.split('[^A-Z]', upper_page):
            if e == word.upper():
                count += 1
        domain[name][0] = idx
        domain[name][1] += count
        # 외부링크에 점수 더해주기
        for outer in outer_link:
            domain[outer][1] += count / len(outer_link)
        # print(f'현재 링크 이름 = {name}')
        # print(f'기본 점수 = {count}')
        # print(f'외부 링크 = {outer_link}')
        # print(f'기본점수 / 외부링크 수 = {count / len(outer_link)}')
        # print(f'domain[{name}] = {domain[name]}')
        # print()
    # 매칭점수가 가장 높은 웹페이지의 index를 구하라.
    # 만약 그런 웹페이지가 여러 개라면 그중 번호가 가장 작은 것을 구하라.
    ans = sorted(domain.values(), key=lambda x: (-x[1], x[0]))
    # print(ans)
    return ans[0][0]
    
solution('blind',
         [
             "<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 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>\nSuspendisse potenti. Vivamus venenatis tellus non turpis bibendum, \n<a href=\"https://a.com\"> Link to a </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>"]
         )

2. 후기

2-1. 출력 예시

현재 링크 이름 = A.COM
기본 점수 = 3
외부 링크 = ['B.COM']
기본점수 / 외부링크 수 = 3.0
domain[A.COM] = [0, 3.0]

현재 링크 이름 = B.COM
기본 점수 = 1
외부 링크 = ['A.COM', 'C.COM']
기본점수 / 외부링크 수 = 0.5
domain[B.COM] = [1, 4.0]

현재 링크 이름 = C.COM
기본 점수 = 1
외부 링크 = ['A.COM']
기본점수 / 외부링크 수 = 1.0
domain[C.COM] = [2, 1.5]

[[0, 4.5], [1, 4.0], [2, 1.5]]
현재 링크 이름 = CAREERS.KAKAO.COM/INTERVIEW/LIST
기본 점수 = 0
외부 링크 = ['PROGRAMMERS.CO.KR/LEARN/COURSES/4673']
기본점수 / 외부링크 수 = 0.0
domain[CAREERS.KAKAO.COM/INTERVIEW/LIST] = [0, 0.0]

현재 링크 이름 = WWW.KAKAOCORP.COM
기본 점수 = 1
외부 링크 = ['HASHCODE.CO.KR/TOS']
기본점수 / 외부링크 수 = 1.0
domain[WWW.KAKAOCORP.COM] = [1, 1.0]

ans = [[1, 1.0], [999, 1.0], [0, 0.0], [999, 0.0]]

2-2. 정규식 찾기

문제 설명: 단어는 알파벳을 제외한 다른 모든 문자로 구분한다.
-> re.split('[^A-Z]', upper_page)

어떤 정규식을 써야 word를 한 번에 찾을 수 있을지 머리가 복잡했다. 하지만 설명란에 어떤 정규식을 써야할지 친절하게 알려주고 있었다.

^은 부정을 의미하고, 본인의 경우 페이지를 대문자로 변환시켰기 때문에 a-zA-z를 사용하지 않고 대문자만 사용했다. 문제 설명과 그대로 알파벳이 아닌 모든 문자를 기준으로 split() 한다는 의미이다.

처음에는 [\s\d](공백과 숫자 기준, but 특수문자 불가능), [^\w] 등 여러가지 생각을 했지만 문제를 다시 읽어보고나서야 정규식을 완성시켰다.

2-3. 테스트 케이스 8, 13

tc8, tc17 에서 오류가 계속 발생했다. 다시 문제를 읽었다.

만약 그런 웹페이지가 여러 개라면 그중 번호가 가장 작은 것을 구하라.

ans = sorted(domain.values(), key=lambda x: (-x[1], x[0])) 에서 x[0] 에 대한 정렬을 하지 않아서 계속 오답이 나왔던 것이었다.

문제의 조건을 빼먹지 않고 읽으려고 항상 다짐하지만 문제가 길어지면 집중력이 부족해지는 것 같다. 오답이 나와도 틀린 이유를 잘 모르겠다면 다시 한번 문제를 꼼꼼하게 읽어보도록 하자.

2-4. 테스트케이스 7, 9

CONTENT="HTTPS://를 찾는게 아니라 <META PROPERTY="OG:URL" CONTENT="HTTPS://를 찾아야한다.

HREF="HTTPS://또한 <A HREF="HTTPS://를 찾아야 한다.

profile
안녕하세요!

0개의 댓글