[プログラマ]マッチングスコア


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


tc 8、tc 17はエラーを続行します.問題を読み直した.
そのようなページが複数ある場合は、その中で一番小さい番号を求めます.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://を探しています.