Case = int(input())

def priority_print(queue, M, print_count):
    priority = max(queue.values())
    
    for key, item in queue.items():
        if(priority == item):
            if(M == key):
                return print_count
            else:
                queue.pop(key)
                return priority_print(queue, M, print_count + 1)
        else:
            cur_key = key
            cur_item = item
            queue.pop(cur_key)
            queue.update({cur_key: cur_item})
            return priority_print(queue, M, print_count)

for _ in range(Case):
    # N : 문서의 수 
    # M : 몇번째로 인쇄될지 궁금한 문서의 위치
    N, M = map(int, input().split())
    
    if(N == 1):
        dummy = input()
        print(1)
        continue
    
    num_list = map(int, input().split())
    
    queue = dict()
    for i, num in enumerate(num_list):
        queue[i] = num
        
    print(priority_print(queue, M, 1))

'# 코딩 문제 관련 > 파이썬' 카테고리의 다른 글

백준 10866번(python)  (0) 2019.06.20
백준 11866번, 1158번(python)  (0) 2019.06.20
백준 1260번(python)  (0) 2019.06.18
백준 10845번(python)  (0) 2019.06.17
백준 2504번(python)  (0) 2019.06.03

이 글은 파이썬에서 * 표현이 어떤 용도로 사용하는지에 대해 다룹니다.


1. 곱셈과 거듭제곱

- 굳이 코드를 붙이지 않아도 다들 아실거라고 생각합니다.

  • 1 * 2 = 2
  • 2 ** 2 = 4

2. 리스트 확장

* 를 사용하여 리스트를 간단히 확장할 수 있습니다.


3. 가변인자

가변인자란, 이름 그대로 길이가 변할 수 있는 argument를 말합니다. 

임의의 함수에 인자로 몇개의 데이터가 들어올지 모르게 되는 경우에 사용하면 편리합니다. 

이때 여러 api나 잘 짜여진 코드를 구경하다보면 함수에 *args**kwargs라고 되있는 표현들을 많이 볼 수 있습니다.

이게 바로 가변인자를 사용하겠다는 의미입니다. 한개와 두개의 차이는 positional과 keyward 인자의 차이입니다. 

이름만 들어서는 낯설 수 있지만, 사실 이미 사용하고 있을지도 모릅니다. 각각은 아래와 같습니다.

def function(a, b = None):
...

여기서 a는 positional arguments, b는 keyword arguments라고 칭합니다. 모두 아시다시피 a는 값이 없는 경우 error가 뜨게 되며, b는 default값으로 None값을 주게 되죠.

아래 예제처럼 args는 tuple 또는 list, kwargs는 dict에 저장되어 출력되는 것을 볼 수 있으며, 동시에 사용할 수도 있습니다. 

def args_function(*args):
    print(args)

def kwargs_function(**kwargs):
    print(kwargs)
    
args_function('a', 'b') # ('a', 'b')
kwargs_function(a = 100, b = 200) # {'a':100, 'b':200}

4. Unpacking

알고리즘을 짜다보면 결과부분을 출력할 때, for-lopp를 이용하여 list를 순회하며 출력하는 경우가 있습니다.

# list unpacking
test = [1, 2, 3, 4]
print(*test) # 1 2 3 4

# tuple unpacking
test = (5, 6, 7, 8)
print(*test) # 5 6 7 8

이렇게 사용하면 코드 길이도 줄고 편리하죠?

다음은 각 변수 중 하나에 가변적으로 할당하고 싶은 경우입니다. 

다음과 같이 사용할 수도 있습니다.

test = [1, 2, 3, 4, 5]

*a, b = test
print(a, b) # [1, 2, 3, 4], 5

a, *b, c = test
print(a, b, c) # 1, [2, 3, 4], 5


N, M, V = map(int, input().split())

matrix = [[0] * (N + 1) for _ in range(N+1)]
for _ in range(M):
    link = list(map(int, input().split()))
    matrix[link[0]][link[1]] = 1
    matrix[link[1]][link[0]] = 1
    
def dfs(current_node, row, foot_prints):
    foot_prints += [current_node]
    for search_node in range(len(row[current_node])):
        if row[current_node][search_node] and search_node not in foot_prints:
            foot_prints = dfs(search_node, row, foot_prints)
            
    return foot_prints

def bfs(start):
    queue = [start]
    foot_prints = [start]
    while queue:
        current_node = queue.pop(0)
        for search_node in range(len(matrix[current_node])):
            if matrix[current_node][search_node] and search_node not in foot_prints:
                foot_prints += [search_node]
                queue += [search_node]
                
    return foot_prints

print(*dfs(V, matrix, []))
print(*bfs(V))

이번 코드는 

https://this-programmer.com/entry/백준1260파이썬-DFS와-BFS

 

[백준/1260/파이썬3(python3)] DFS와 BFS

[백준/1260/파이썬] DFS와 BFS 문제 그래프를 DFS로 탐색한 결과와 BFS로 탐색한 결과를 출력하는 프로그램을 작성하시오. 단, 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문하고,..

this-programmer.com

블로그를 참고하였습니다. 코드가 깔끔해서 보는사람 입장에선 이 코드를 포스팅하는게 낫다고 생각...

'# 코딩 문제 관련 > 파이썬' 카테고리의 다른 글

백준 11866번, 1158번(python)  (0) 2019.06.20
백준 1966번(python)  (0) 2019.06.20
백준 10845번(python)  (0) 2019.06.17
백준 2504번(python)  (0) 2019.06.03
백준 9012번(python)  (0) 2019.06.02


 

class Queue:
    def __init__(self):
        self.list = []
        
    def push(self, x):
        self.list.append(x)
        
    def pop(self):
        if(self.empty()):
            return -1
        else:
            output = self.list[0]
            self.list = self.list[1:]

            return output

    def empty(self):
        return 1 if len(self.list) == 0 else 0
    
    def size(self):
        return len(self.list)
    
    def front(self):
        if(self.empty()):
            return -1
        else:
            return self.list[0]
        
    def back(self):
        if(self.empty()):
            return -1
        else:
            return self.list[-1]
        
Case = int(input())
queue = Queue()

while(Case > 0):
    Case -= 1
    input_split = input().split()
    
    order = input_split[0]
    
    if(order == 'push'):
        queue.push(input_split[1])
    elif(order == 'pop'):
        print(queue.pop())
    elif(order == 'size'):
        print(queue.size())
    elif(order == 'empty'):
        print(queue.empty())
    elif(order == 'front'):
        print(queue.front())
    elif(order == 'back'):
        print(queue.back())
    else:
        print('xx')

'# 코딩 문제 관련 > 파이썬' 카테고리의 다른 글

백준 1966번(python)  (0) 2019.06.20
백준 1260번(python)  (0) 2019.06.18
백준 2504번(python)  (0) 2019.06.03
백준 9012번(python)  (0) 2019.06.02
백준 1874번(python)  (0) 2019.06.02

네이버 크롤링은 매우 간단하다.

이 글에서는 영화를 검색했을 경우, 네티즌의 리뷰 갯수가 몇개나 등록되어 있는지를 크롤링하는 코드를 포스팅한다.

# 현재 내가 가지고 있는 영화의 타이틀을 저장함
full_title =np.array([train_and_test['title'].apply(lambda x : x.split(' '))]).reshape(-1, )

# requests, bs4가 없다면 설치해야 한다.
import requests
from bs4 import BeautifulSoup

# 네이버에서 영화를 검색할 시 공통적으로 생성되는 쿼리문은 아래와 같다
# 따라서 영화 이름과 url을 붙여준 리스트를 한번 더 생성해보자
full_url = list()
for title in full_title:
    url = 'https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query=영화'
    for word in title:
        url += '+'
        url += word
    
    full_url.append(url)

# 이제 영화 리뷰 수, 즉 별점을 몇명이나 주었는지에 대한 정보를 담을 dataframe을 생성한다.
star_num_df = pd.DataFrame(columns=['title', 'star_num'])

# headers
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; ko-KR))',
}

# 네이버에서는 우리가 찾을 값을 cont_p로 정의해두었다. 그에 맞춰 이름을 정의하자.
cont_p_list = list()

# main code
for i, (url, title) in enumerate(zip(full_url, train_and_test['title'])):
    print(i)
    response = requests.get(url, headers = headers)
    html = response.text
    
    soup = BeautifulSoup(html, 'lxml')
    
    # cont_p를 찾아준다.
    em = soup.find('em', {'class':'cont_p'})
    
    if(em is None):
        num_df.loc[i, 'title'] = title
        num_df.loc[i, 'star_num'] = 0
    else:
    	# 자신이 찾고 싶은 데이터에 맞게 찾아오면된다. 자세한건 soup.find를 검색해보자
        for em in soup.find('em', {'class':'cont_p'}):
            num_df.loc[i, 'title'] = title
            num_df.loc[i, 'star_num'] = em

지금 글부터는 자바스크립트 형태로 되어 있어 위의 코드로 찾을 수 없는 데이터를 찾으려고 한다.

어떻게 알 수 있냐면, 분명히 페이지 소스에서는 존재하는 데이터가 soup.find로 찾으려고 할때 None값이 리턴되는 경우가 생긴다면 의심해 볼 필요가 있다.

위의 코드는 해당 데이터가 자바스크립트 형태로 되어 있을 시, soup.find를 통하여 클래스를 찾을 수가 없다. 따라서 아래와 같이 코드를 변경해주어야 한다.

이번 예제는 네이버에서 영화를 검색했을 때, 영화의 하트 갯수를 찾을 것이다. (검색하면 쉽게 찾아볼 수 있음)

# 영화의 제목을 저장하자
full_title =np.array([train_and_test['title'].apply(lambda x : x.split(' '))]).reshape(-1, )

# 이부분까지도 위와 같다.
import requests
from bs4 import BeautifulSoup

full_url = list()
for title in full_title:
    url = 'https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query='
    for word in title:
        url += '+'
        url += word
        
    url += '+영화'
    full_url.append(url)
    
# 우리가 원하는 데이터는 하트 갯수이다. 이를 저장할 dataframe을 생성하자
heart_num_df = pd.DataFrame(columns=['title', 'heart_num'])

# main code
# 여러가지 방법이 있겠지만 이 글에서는 크롬을 이용한다
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import time

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('headless') # headless 모드를 했을 때 실행이 안된다. 일단 생략.

# driver = webdriver.Chrome(ChromeDriverManager().install())
driver = webdriver.Chrome(executable_path='/Users/johwiyong/.wdm/chromedriver/74.0.3729.6/mac64/chromedriver')

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; ko-KR))',
}

# 네이버에서는 우리가 찾을 데이터를 u_cnt로 정의해두었다. 
u_cnt_list = list()

for i, (url, title) in enumerate(zip(full_url, train_and_test['title'])):
    print(i)
#     response = requests.get(url, headers = headers)
    driver.get(url)
    driver.implicitly_wait(10) # 작동하지 않는 것 같다.
    # 이만큼의 시간을 기다려주는 이유는 데이터가 불려오기 전에 다음 페이지로 넘어갈 경우
    # None을 return하는 경우가 발생하는 점을 방지
    time.sleep(3) 
    html = driver.page_source
    driver.implicitly_wait(10)
    
    # 여기서부터는 위와 비슷하다
    soup = BeautifulSoup(html, 'lxml')
    
#     print(soup.find_all('em'))
    u_cnt_list = soup.find_all('em', 'u_cnt _cnt')

    if(len(u_cnt_list) == 0):
        print(title)
        heart_num_df.loc[i, 'title'] = title
        heart_num_df.loc[i, 'heart_num'] = 0
    else:
        heart_num_df.loc[i, 'title'] = title
        em = soup.find_all('em', 'u_cnt _cnt')[0].get_text()
        heart_num_df.loc[i, 'heart_num'] = em
        
    print(i, em)