[프로그래머스/Lv2] 할인 행사
https://school.programmers.co.kr/learn/courses/30/lessons/131127
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
코드
from collections import deque
def solution(want, number, discount):
want_dict = {}
for goods, n in zip(want, number):
want_dict[goods] = n
deq_discount = deque(discount)
answer = 0
check = True
while check:
try:
discount_dict = {}
for i in range(10):
try:
discount_dict[deq_discount[i]] += 1
except:
discount_dict[deq_discount[i]] = 1
discount_check = 0
for key, value in want_dict.items():
try:
if discount_dict[key] >= value:
discount_check += 1
except:
pass
if discount_check == len(want_dict):
answer += 1
deq_discount.popleft()
except:
check = False
return answer
설명
처음 문제를 보면 글자가 굉장히 많아서 겁먹을 수도 있는데
다른 2레벨 문제들에 비하면 굉장히 쉬운 편인것 같다.
문제에 대한 상세 설명도 필요 없이 차근차근 한 번 읽어보면 이해가 잘 된다.
문제는 아래와 같은 방법으로 풀어볼 것이다.
우선 구매하고 싶은 물건들의 이름과 개수를 기록하는 딕셔너리를 만든다.
그 후 할인품목 리스트(discount)의 첫 원소부터 10개까지 물건들의 각 개수를 세어 마찬가지로 딕셔너리로 만든다.
첫번째 딕셔너리의 물건들을 키로 두번째 딕셔너리를 검색한다.
그렇게 나온 값은 회원가입한 날부터 열흘동안 해당 물건에 대한 할인 횟수를 나타낼 것이다.
그 값이 첫번째 딕셔너리의 물건에 해당하는 값과 같거나 크다면 일단 그 품목은 조건에 맞다고 체크해둔다.
이렇게 체크한 개수가 첫번째 딕셔너리의 길이와 같다면 이 날짜에 회원등록하면 모든 물건을 할인해서 살 수 있다는 뜻이 된다.
위 과정을 discount 리스트의 가장 왼쪽 원소를 pop하면서 반복하는데, 길이가 10보다 작으면 반복을 멈춘다.
want_dict = {}
for goods, n in zip(want, number):
want_dict[goods] = n
want_dict는 원하는 물건들과 그 개수를 키와 값으로 하는 딕셔너리이다.
주어진 want와 number 리스트로 want_dict를 초기화한다.
from collections import deque
deq_discount = deque(discount)
discount를 deque로 변환해 deq_discount에 저장한다.
pop(0)는 O(n)의 시간복잡도를 가지는 반면
deque의 popleft()는 O(1)의 시간복잡도를 가지기 때문에
단순 리스트로 구현하기보다 deque로 구현했다.
answer = 0
check = True
while check:
answer는 정답을 기록하는 변수이다.
check가 True일 때 아래 while문이 동작한다.
try:
discount_dict = {}
for i in range(10):
try:
discount_dict[deq_discount[i]] += 1
except:
discount_dict[deq_discount[i]] = 1
discount_check = 0
for key, value in want_dict.items():
try:
if discount_dict[key] >= value:
discount_check += 1
except:
pass
if discount_check == len(want_dict):
answer += 1
deq_discount.popleft()
except:
check = False
while문의 내부 동작이다.
이 코드에서 쪼개가면서 다시 설명한다.
discount_dict = {}
for i in range(10):
try:
discount_dict[deq_discount[i]] += 1
except:
discount_dict[deq_discount[i]] = 1
discount_dict는 할인 품목과 그 개수를 딕셔너리로 표현한 변수이다.
0부터 9까지(10개) 반복한다.
discount_dict에 deq_discount[i](물건 이름)이 이미 키로 존재한다면 그 키에 해당하는 값에 1을 더한다.
그렇지 않다면 deq_discount[i]을 키로 가지는 값을 1로 초기화한다.
discount_check = 0
for key, value in want_dict.items():
try:
if discount_dict[key] >= value:
discount_check += 1
except:
pass
discount_check는 원하는 물건의 할인 여부를 기록하는 변수이다.
want_dict의 키와 값을 꺼내며 반복한다.
만약 discount_dict에 key에 해당하는 키가 존재한다면 그 키에 해당하는 값과 value를 비교하여
value보다 크거나 같다면 discount_check에 1을 더한다.
그렇지 않다면 아무 작업없이 넘어간다.
if discount_check == len(want_dict):
answer += 1
구해놓은 discount_check와 want_dict의 길이를 비교하여 같다면 answer에 1을 더한다.
deq_discount.popleft()
deq_discount의 가장 왼쪽 원소를 pop한다.
여기까지가 가장 바깥쪽 try문의 작업 내용이다.
check = False
except문의 동작은 check를 False로 변경하여 while문을 종료하도록한다.
여기서 가장 바깥쪽의 try, except문의 분기를 담당하는 에러는 IndexError로
deq_discount의 길이가 10보다 작게 되면 IndexError가 발생하여 while문이 종료된다.
return answer
구해놓은 answer를 반환한다.
'코딩테스트 > 연습문제' 카테고리의 다른 글
[프로그래머스/Lv2] 가장 큰 수 (0) | 2022.12.01 |
---|---|
[프로그래머스/Lv2] 다리를 지나는 트럭 (0) | 2022.11.30 |
[프로그래머스/Lv2] 2 x n 타일링 (0) | 2022.11.25 |
[프로그래머스/Lv2] 2개 이하로 다른 비트 (0) | 2022.11.24 |
[프로그래머스/Lv2] 게임 맵 최단거리 (0) | 2022.11.23 |