ASAC 빅데이터 분석가 7기/ASAC 일일 기록

ASAC 빅데이터 분석가 과정 12일차 - 1 (24.12.19)

junslee 2024. 12. 19. 09:27

01_python

04_cotest

20_탐색_2022_양늑대

# ref : https://school.programmers.co.kr/learn/courses/30/lessons/92343
# 양 늑대 문제

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

def solution(info, edges):
    answer = 0
    return answer

 

# 실제 이 문제 정답률 : X% 정답률!
==> 조금 공부들을 하시고, 탐색쪽에 대해서 여러 유형들에 대해서 좀 감을 잡으면 코드 자체는 복잡하지는 않다.
       : 일반적으로 카카오 문제는 앞에가 쉽고 뒤에가 어렵다.
       : 종종 뒤에도 가끔 풀 수 있는 문제들이 있다.

       : 처음에 문제를 받고, 전체 문제들을 한 번 체크해 보는 습관 필요하다.


# 문제 해석

  조건 : 양의 수 > 늑대의 수
              (조건을 만족해야 계속 진행 가능)
             양의 수 <= 늑대의 수 : 끝!!
  결과 : 양의 수가 최대인 값을 구하자!!

 

  출발점은 무조건 "양"이다.

  트리의 구조는 노드끼리의 연결성으로 입력되어 있다.

 


주의! 탐색이 너무 많거나 오래 걸리면 시간 오바!

# 입력에 대한 코드화 작업을 예!!!

t_info = [0,0,1,1,1,0,1,0,1,0,1,1]
# 도시의 수 : t_info 원소 수
t_edge = [[0,1],[1,2],[1,4],[0,8],[8,7],[9,10],[9,11],[4,3],[6,5],[4,6],[8,9]]
# { 노드번호 : [연결된 노드] }

# 양/늑대의 정보는 이미 입력에 있으니, 여기선 연결성만 정리
# 늑대/양에 대한 정보를 추가할 수 있다 ( a- b : 10거리)
t_n = len(t_info) # 총 마리수
t_tree = {i:[]  for i in range(t_n)} # 마리 수 만큼 리스트 초기화
for s,e in t_edge:            # s : 노드 번호, e : 연결된 노드
    t_tree[s].append(e)     # 노드 번호 자리에 연결된 노드 추가하기
t_tree
{0: [1, 8],
 1: [2, 4],
 2: [],
 3: [],
 4: [3, 6],
 5: [],
 6: [5],
 7: [],
 8: [7, 9],
 9: [10, 11],
 10: [],
 11: []}

# DFS/BFS ---> deque

from collections import deque
# 속도 이슈가 있다!
# 큐로 해본다면 쉽게 변환하기 위한 생각을 해야 한다.

def solution(info, edges):
    answer = 0  # 지금까지 모인 양의 수! : 선택정렬
 
    # 1) 입력에 대한 처리 : 주어진 tree/네트워크 (노드 번호 중심)
    # 노드 번호 : key
    # 연결된 노드들 : value
    # 노드의 수 : len(info)
    n = len(info)
    # 0번 노드가 1,8번 연결 : {0:[1,8]}
    tree = {i:[]  for i in range(n)} # 위에 내용 참고
    for s,e in edges: 
        tree[s].append(e)
    # {0: [1, 8],1: [2, 4],2: [],3: [],4: [3, 6],5: [],6: [5],7: [], 8: [7, 9],9: [10, 11],10: [],11: []}
    # 트리 모양을 인접 리스트 방식으로 파이썬의 Dict로 코드화한다.

    # 2) 실제 다 돌아가면서 탐색
    # 현재위치,  이동가능한 노드, 양, 늑대
    que = deque( [[0, tree[0], 1, 0]]) # [ [a,b,c,d],[z,g,d,d]]
    while que:
        # 일단 할 일에서 꺼내자 : popleft(), pop()
        now_node, move_nodes, num_sheep, num_wolf = que.pop() # popleft
        # 기존의 양의 수보다, 지금 경로의 양의 수가 많은면 갱신!
        if answer < num_sheep:
            answer = num_sheep

        # 이제 여기서 더 이동을 할 수 있는지에 대한 롤링!
        for i, node in enumerate( move_nodes):
            # 이동을 해본다면,,,,거기에 늑대가 있을 수 있음..
            if info[node] == 1: # 늑대가 있다면,,,,,
                # 늑대가 양보다 같거나 큰지 체크!!!!
                if num_sheep > num_wolf + 1:
                    que.append([ node,move_nodes[:i]+move_nodes[i+1:]+tree[node],
                                num_sheep,num_wolf + 1])
            else: # 양이 있다면,,,,
                que.append( [node,move_nodes[:i]+move_nodes[i+1:]+tree[node],
                                num_sheep+1,num_wolf])

    return answer

  // (복습 미완)


# test1
a = [0,0,1,1,1,0,1,0,1,0,1,1]
b = [[0,1],[1,2],[1,4],[0,8],[8,7],[9,10],[9,11],[4,3],[6,5],[4,6],[8,9]]
solution(a,b)
5
# test2
a = [0,1,0,1,1,0,1,0,0,1,0]
b = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6],[3,7],[4,8],[6,9],[9,10]]
solution(a,b)
5

[1,2]
[1, 1,5,6] # 지금 코드 상은 이렇게 정보가 추가.....
[1,5,6]    # ---> 시간 오바 발생하면,,,도는 부분을 컴펙트하게 조정!!!
# --> 돌려도 시간 오바 안 걸려서,,,굳이 안 했습니다....


# 이런 유형들이 탐색기반의 문제들이 걸러내기가 용이함!!!
==> 비슷한 유형이지만, 잘 안 보일 수 있어요!!!!
==> 어설프게 공부하면,,,,잘 못풀어요!!!! + 중/중상
       : 킬러 파트 중 하나임!!!!!!
==> 사고의 유연성을 가지셔야 함!!! + 대표적인 탐색의 여러 유형 문제들!!
       : 문제도 많이 풀어야 하고,,,유형별로 정리!!!!!
/////////////////////////////////////////////////////////////////

# 탐색의 가장 기본이 : 여러가지 모든 경우의 수!!!
===> 수학적의 경우의 문제와 유사한 스타일!!!!!!
https://school.programmers.co.kr/learn/courses/30/lessons/92342
: 2022년 블라인드 4번 문제!!!
# 꼭!! 많은 문제들 & 유형들을 풀어봐야 함!!!!!!

+++ 경우의 수 문제
+++ 최단거리 알고리즘

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr


03_pandas

00_code

06_json_kobis_dict

# 목적1. 앞에서 kobis api에서 영화 목록에 대한 정보를 요청!
               DF으로 정리하는 과정 -> 리스트
               Dict  + 있는 정보 다 DF으로 담아보자!

# 목적2. requests 패키지
              json 변환에 대한 모듈이 이미 내장되어 있다
              import json (X) 


# 필요한 모듈

import pandas as pd
import requests      #  anaconda, colab은 기본 내장 되어 있음
# import json (X) 필요 없다

 

# 구조적으로 변경 (이전에 한 내용 불러오기)

# 1) base_url :
base_url = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieList.json"
# 2) 실제 요청 파라미터들에 대해서 dict을 표현
#      api상에서 사용할 수 있는 요청인터페이스 : key(문자열)
#                                          요청인자에 대한 값 : value(숫자,문자)
#      ex) key, itemPerPage
my_params = {
    "key":"e5b253a83f004635cd7fd625e9a0a839",
    "itemPerPage" : 50
}
# 3) 해당 요청에 대한 실제 접속
res = requests.get(base_url, params = my_params)
# 4) FM적으로 하게 되면 http통신에 대한 에러/중간 프로세스를 알아야한다.
#  https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses
if res.ok:
    result = res.json()
else:
    print("Check your HTTP Response code!!!!")
result
 

HTTP response status codes - HTTP | MDN

HTTP response status codes indicate whether a specific HTTP request has been successfully completed. Responses are grouped in five classes:

developer.mozilla.org

# 출력 생략

# 어제 접속할 주소 생성 코드 (이전에 한 내용 불러오기)

# 기본 주소
url_p1 = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieList.json"
# 필수 항목 : key
key = "e5b253a83f004635cd7fd625e9a0a839"
# 부가 요청사항 : itemPerPage을 이용해서 50개로 확장
url_p2 ="50"
# 위의 사항이 반영된 주소
url = url_p1 +"?key=" + key+"&itemPerPage="+url_p2
url

 

http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieList.json?key=e5b253a83f004635cd7fd625e9a0a839&itemPerPage=50

type(result)
dict
result.keys()
dict_keys(['movieListResult'])

 

# 어제 데이터 처리 방식은.

[
    [111,광해  ,,,,,],
    [222,모아나,,,,,],
    .,..
]
[
    {"movieCd":111, "movieNm":"광해"  ,,,},
    {"movieCd":222, "movieNm":"모아나",,,},
    ,,,,
]

# 전체 영화에 대한 정보를 담을 리스트 만들기

new_list = []
# idx : 정수 인덱스 (감독 정보 처리)
# data : 개별 영화에 대한 정보 - dict
for idx, data in enumerate(result["movieListResult"]["movieList"] ):
    one_data = data

    new_list.append( one_data)
new_list
# 출력 생략
new_list[0]
{'movieCd': '20241180',
 'movieNm': '괜찮아, 앨리스',
 'movieNmEn': 'Efterskole, Going to the Wonderland Korea',
 'prdtYear': '2023',
 'openDt': '20241113',
 'typeNm': '장편',
 'prdtStatNm': '개봉',
 'nationAlt': '한국',
 'genreAlt': '다큐멘터리',
 'repNationNm': '한국',
 'repGenreNm': '다큐멘터리',
 'directors': [{'peopleNm': '양지혜'}],
 'companys': [{'companyCd': '20242663', 'companyNm': '오마이뉴스'}]}
pd.DataFrame(new_list)
# 출력 생략 - DF
pd.DataFrame(result["movieListResult"]["movieList"] )
# 출력 생략 - DF

# 리스트의 DF를 Dict의 DF으로 재구성하기

[
    [,,,,],
    [,,,,],
]
# --> DF
[
    {:,:,:,:,},
    {:,:,:,:,},
    ,,,,
]
# --> DF

 

pd.DataFrame(new_list)[
    {"movieCd":111,"movieNm":"광해", "directors":[~~~~~]},
    {"movieCd":222,"movieNm":"모아나", "directors":[~~~~~]},
]

[
    {"movieCd":111,"movieNm":"광해", "directors":[~~~~~], "direcotor":"AAA"},
    {"movieCd":222,"movieNm":"모아나", "directors":[~~~~~],"direcotr":""},
]

# 감독에 대한 정보들을 처리하고자 한다.

directors_list = []
for idx, data in enumerate(result["movieListResult"]["movieList"] ):
    directors_list.append(data["directors"] )
directors_list
# 출력 생략

 

# 참고) 리스트의 병합 : FM --> extend , AM --> +
# 참고) Dict에서 병합

d1 = {"A":1234,"B":5678}
d2 = {"B":9999, "C":1000}
print(d1)
print(d2)
{'A': 1234, 'B': 5678}
{'B': 9999, 'C': 1000}

 

# d1에 d2를 반영해서 업데이트

d1["B"] = 9999
d1["C"] = 1000
d1
{'A': 1234, 'B': 9999, 'C': 1000}
d1 = {"A":1234,"B":5678}
d2 = {"B":9999, "C":1000}

{**d1, **d2}
{'A': 1234, 'B': 9999, 'C': 1000}

 

# * 기호를 본 경험
  1) *args : 파이썬에서 여러개의 입력에 대한 합을 구하는 함수 : 리스트
  2) **args : def aa(p="12", cc=1234):
                   dict(cc:99, p="34") **args

 

# 전체 영화에 대한 정보들을 담을 리스트

new_list = []
# idx : 정수 인덱스 (감독 정보 처리)
# data : 개별 영화에 대한 정보 - dict
for idx, data in enumerate(result["movieListResult"]["movieList"] ):
    one_data = data
    if len(directors_list[idx]) != 0:
        one_data = {**one_data, **directors_list[idx][0]}
        # 1번 감독에 대한 정보 추출 directors_list[idx][0]
        # {'peopleNm': '양지혜'}
        # one_data = {"movieCd":111,"movieNm":"광해", "direcotors":[{'peopleNm': '양지혜'}] }
        # +++
        # {"movieCd":111,"movieNm":"광해", "direcotors":[{'peopleNm': '양지혜'}],'peopleNm': '양지혜' }
    new_list.append(one_data)  # 1번 감독에 있으면 추가
print(new_list)
# 출력 생략
pd.DataFrame(new_list)
# 출력 생략


# 정리)
1. http통신에서 요청 파라미터에 대한 dict로 정리해서 보내는 방식
2. json 양식에서 주로 덩어리로 주고(파이썬 리스트로)
     + 그 안에 있는 개별 정보들에 대해서 정리 (dict)
     [  {~~~~}, {~~~~~},{~~~~~},...] 구조
     # 통으로 DF를 넘길 수 있다!
3. 받은 과정에서 원본 json파일로 로컬이나 DF 로컬로 추가해서 백업 필수!
    추가적인 전처리들은 추후에 진행을 하면 된다.
     json으로 요청하고 받을 때 : 크게 처리하는 방식도 잘 알아두어야 한다.