고딩왕 코범석

[프로그래머스] 매칭 점수, Python3 본문

Computer Science/Algorithm

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

고딩왕 코범석 2021. 1. 20. 13:17
반응형

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

문제는 여기!

이번 문제는 정규 표현식을 통해 문제에서 원하는 문자열을 도출하는 과정이 어려워서 다른 분들의 코드를 참조했다.

  • 제한사항 및 유의사항

    • 기본점수 : 해당 웹페이지에서 검색된 키워드의 갯수(대소문자 무시)

    • 외부 링크 수 : 해당 웹페이지에서 다른 외부 웹페이지로 연결된 링크 갯수

    • 링크점수 : 해당 웹페이지에서 링크가 걸린 다른 웹페이지의 기본점수 / 그 다른 웹페이지의 외부링크 수

      • 이 부분이 조금 헷갈렸다. 문제의 이미지를 빌려보자면

      image

      • B 웹페이지와 C 웹페이지는 A 웹페이지를 외부 링크로 참조했다.
      • 그럼, A 웹페이지의 링크 점수는 (B의 기본점수 / B의 외부링크수) + (C의 기본점수 / C의 외부링크수) 가 되겠다.
    • 우리가 원하는 매칭 점수는 기본점수 + 링크점수가 되겠다.

  • 풀이전략

    • 정규표현식과 파이썬의 re 모듈 사용법을 알아야 한다. 구글신에게 여쭤보면 나보다 아주 잘 설명하신 분들이 많이 계셔서 검색으로 찾아보는 것을 추천!

    • 이 문제를 위해 딕셔너리를...다섯개 선언했다.. 하나씩 다 설명 드리겠음

      image

      • page_url_index : 문제에서는 인덱스를 찾아야 하므로 인덱스를 dict로 선언했다.
      • page_url_score : 해당하는 url의 점수를 보관한다.
      • page_exurl_url : 현재 url에서 참조하는 외부 url을 의미한다
        • ex) 만약 a.com이 b.com을 참조한다면
        • page_exurl_url = { "b.com" : [a.com] }
      • page_url_exurl_count : 현재 url에서 외부 url의 갯수를 저장하는 딕셔너리
      • page_url_exurl_score : 현재 url의 링크점수 합산을 저장하기 위한 딕셔너리
    • 해당 page들을 lower 처리해줘서 소문자로 만든다.

      • 이유 : 대소문자의 구분 없이 키워드를 찾아야 하므로!
    • 그 다음 re 모듈을 이용해 메타태그 내에 현재 url을 추출하여 page_url_index에 저장

    • 기본 점수를 구한다.

      • 문제를 잘 읽어보면 알파벳을 제외한 모든 문자를 구분한다고 되어있다. 단순 문자열을 split하면 안된다!
    • 현재 페이지의 외부 url들을 구하고 page_exurl_url 딕셔너리에 저장

      • 이 과정에서 현재 url의 외부링크 수를 구해준다. page_url_exurl_count 딕셔너리에 저장!
    • 이제 본격적으로 매칭점수를 구해보자

      • page_url_exurl_score 라는 딕셔너리를 선언하고 여기에 링크점수들을 구해주자.
      • 계산한 링크점수들의 key(url), value(링크점수)들을 page_url_score에 대입하자.
    • page_url_score를 점수 내림차순으로 정렬해서 0번째 튜플 0번째 원소를 key(최고 매칭점수 url)로 page_url_index 딕셔너리에서 찾자.

import re


def solution(word, pages):
    word = word.lower()

    page_url_index = {}
    page_url_score = {}
    page_exurl_url = {}
    page_url_exurl_count = {}

    for i in range(len(pages)):
        page_lower = pages[i].lower()

        # 해당 url의 index 설정
        url = re.search(r'<meta ([\S]*) content="([\S]*)"/>', page_lower).group(2)
        page_url_index[url] = i

        # 기본점수 구하기
        count = 0
        for split_word in re.split(r'[^a-zA-Z]', page_lower): # 알파벳을 제외한 모든 문자로 나눈다.
            if word == split_word:
                count += 1
        page_url_score[url] = count

        # 외부링크 구하기
        for exurl in re.findall(r'<a href="([\S]*)">', page_lower):
            if exurl not in page_exurl_url:
                page_exurl_url[exurl] = []
            page_exurl_url[exurl].append(url)
            #
            if url not in page_url_exurl_count:
                page_url_exurl_count[url] = 0
            page_url_exurl_count[url] += 1

    # 매칭 점수 계산하기, 링크 점수를 담을 임시 변수 생성
    page_url_exurl_score = {}
    for exurl, urls in page_exurl_url.items():
        if exurl in page_url_score:
            score = 0
            for url in urls:
                score += (page_url_score[url] / page_url_exurl_count[url])
            page_url_exurl_score[exurl] = score

    # 계산한 매칭점수를 page_url_score에 대입
    for url, score in page_url_exurl_score.items():
        page_url_score[url] += score

    # 기록한 score를 점수순으로 정렬, index 리턴
    answer = sorted(page_url_score.items(), key=lambda x: -x[1])
    return page_url_index[answer[0][0]]

이 문제 덕에 re 모듈을 잘 활용하면 문자열을 좀 더 간결한 코드로 다룰 수 있겠다 싶었다.

반응형