문제가 점점 어려워진다. 별 3개가 되는 순간부터 박대가리인 나는 너무 힘들다.
앞으로는 모르는 문제에 대해 이해한 대로 풀이를 쓰는 것 보단 해결한 문제에 대해서 풀이를 쓰려고 한다. 모르는 문제를 붙잡고 있어봤자 제대로 이해도 못하면서 풀이를 쓰는 것이 무슨 의미가 있을까 싶다. 아는 것부터 확실하게 체화해야 겠다.
4주차 | 문제 1. 체크카드
문제
체크 카드를 사용할 때, 가장 중요한 것은 계좌의 남아있는 잔액에 따라서 결제가 잔액이 부족한 경우가 생기기도 한다는 점이다. 구름이는 올바른 소비 습관을 만들기 위해서 지난달 구름이가 카드를 통해서 얼마를 입금하고 결제하였는지 확인하려고 한다.
구름이가 쓰는 체크 카드는 deposit, pay, reservation의 세 가지 기능을 가지고 있다.
- deposit: 주어진 금액 k만큼 계좌에 돈이 입금된다.
- pay: 주어진 금액 k만큼 계좌에서 돈이 결제된다. 단, 계좌의 현재 잔액이 k보다 적다면 결제되지 않는다.
- reservation: 주어진 금액 k만큼 계좌에서 돈이 결제된다. 단, 계좌의 현재 잔액이 k보다 적거나, 대기 목록에 다른 거래가 결제 대기 중이라면 결제 되지 않고 대기 목록의 맨 뒤에 추가된다.
- 대기 목록에 있는 거래들은, 대기 목록에 들어간 순서대로 결제가 가능해지는 즉시 해당 거래의 금액만큼 계좌에서 금액이 차감된 뒤 대기 목록에서 삭제된다.
처음에 구름이의 계좌에 들어있던 금액과 지난달 구름이의 거래 내역이 주어졌을 때, 모든 거래가 종료된 후 구름이의 계좌에 들어있는 잔액을 출력하시오.
입력
첫째 줄에는 처음에 구름이의 계좌에 들어 있던 잔액을 의미하는 정수 N(0≤N≤100,000)과 지난 달 구름이의 거래 횟수 M(1≤M≤10,000)이 주어진다.
둘째 줄부터 M개의 줄에 걸쳐서 거래 종류와 액수가 공백을 두고 주어진다. 거래 종류는 deposit, pay, reservation의 세 문자열 중 하나이며, 거래 액수는 1 이상 1,000 이하의 정수이다.
출력
모든 거래가 종료된 후, 구름이의 계좌에 남아있는 잔액을 출력하시오.
풀이 1 - 통과하지 못한 케이스 존재
코드 제출 시 테스트 케이스 15개 중 10개를 pass, 5개를 fail 하였다. 제출 전 테스트를 위해 주어지는 케이스 2개는 완전히 통과를 했기에 어떤 부분에서 잘못된 것인지 파악할 수 없었다.
import sys
input=sys.stdin.readline
n,m=map(int,input().split()) # 계좌 잔액, 거래 횟수
m_list=[]
for i in range(m):
category,pay=input().split() # 거래 종류, 거래 액수
m_list.append((category,int(pay)))
wait=[]
for c,p in m_list:
if c=='deposit': # 입금
n+=p
if len(wait)>0: # 입금 된 후 n이 wait의 0번 요소보다 크면 결제 후 대기 목록에서 제거
if n>=wait[0]:
n-=wait[0]
wait.remove(wait[0])
if c=='pay': # 결제
if n>=p: # 잔액 n이 거래 액수 p 이상 일 때만
n-=p
if c=='reservation': # 결제
if n>=p: # n이 p 이상 일 때만
if len(wait)>0: # 대기 목록에 다른 거래가 있으면 목록 맨 뒤에 추가
wait.append(p)
else:
n-=p
if n<p:
wait.append(p)
print(n)
풀이 2 - 정답
해설 강의를 보고 잘못된 점을 알게 되었다.
if 문을 쓰면 대기 목록의 맨 앞에 위치한 값만 비교하여 단 한 번 거래가 되기 때문에 while문으로 작성해주어야 한다.
대기 목록에 있는 거래는 가능해지는 즉시(잔액이 결제 금액보다 많을 때) 계속해서 거래가 되어야 하므로 입금(deposit)이 된 순간 while문으로 가능한 거래를 모두 처리해준다.
import sys
input=sys.stdin.readline
n,m=map(int,input().split()) # 계좌 잔액, 거래 횟수
m_list=[]
for i in range(m):
category,pay=input().split() # 거래 종류, 거래 액수
m_list.append((category,int(pay)))
wait=[] # 대기 목록
for c,p in m_list:
if c=='deposit': # 입금
n+=p
# 입금 된 후 n이 wait의 0번 요소보다 크면 결제 후 대기 목록에서 제거
while len(wait)>0 and n>=wait[0]:
n-=wait[0]
wait.remove(wait[0])
elif c=='pay': # 결제
if n>=p: # 잔액 n이 거래 액수 p 이상 일 때만
n-=p
elif c=='reservation': # 결제
if len(wait)==0 and n>=p:
n-=p
else:
wait.append(p)
print(n)