https://www.acmicpc.net/problem/20546
이번 문제는 구현하는데 크게 어려움이 없었다. 백준 기준 실버5 문제이다보니 그런 것 같다.
100
10 20 23 34 55 30 22 19 12 45 23 44 34 38
BNP
준현이는 1월 1일에 10주를 매수한다. 따라서 1월 14일 380원의 자산을 가지게 된다.
성민이는 1월 8일에 5주를 매수한다. 따라서 1월 14일 195원의 자산을 가지게 된다.
15
20 20 33 98 15 6 4 1 1 1 2 3 6 14
TIMING
준현이는 1월 5일에 1주를 매수한다. 따라서 14일의 자산은 14원이다.
성민이는 1월 7일 3주를, 1월 8일 3주를 매수한다. 그리고 1월 13일에 전량 매도한다. 따라서 14일 자산은 36원이다.
#BOJ 문제 20546번 기적의 매매법
# 준현이의 주식 매도 매수
def bnp(stock_price, cash):
having_stock = 0
left_cash = cash
for price in stock_price:
# 보유 현금으로 주식을 살 수 있다면
if left_cash >= price:
# 보유 주식은 몫을 담고
having_stock += left_cash // price
# 현금에는 나머지를 담는다
left_cash %= price
return having_stock * stock_price[-1] + left_cash
# 성민이의 주식 매도 매수
def timing(stock_price, cash):
having_stock = 0
left_cash = cash
for i in range(3, len(stock_price)):
action = what_to_do(stock_price, i)
if action == "buy":
if left_cash >= stock_price[i]:
having_stock += left_cash // stock_price[i]
left_cash %= stock_price[i]
if action == "sell":
if having_stock > 0:
left_cash += having_stock * stock_price[i]
having_stock = 0
return having_stock * stock_price[-1] + left_cash
# timing함수에서 사용되는 의사를 결정하는 함수
def what_to_do(stock_price, i):
if (stock_price[i-1] > stock_price[i-2] and stock_price[i-2] > stock_price[i-3]):
return "sell"
elif (stock_price[i-1] < stock_price[i-2] and stock_price[i-2] < stock_price[i-3]):
return "buy"
return "hold"
cash = int(input())
stock_price = list(map(int, input().split()))
if (bnp(stock_price, cash) > timing(stock_price, cash)):
print("BNP")
elif (bnp(stock_price, cash) < timing(stock_price, cash)):
print("TIMING")
elif (bnp(stock_price, cash) == timing(stock_price, cash)):
print("SAMESAME")
# 준현이의 주식 매도 매수
def bnp(stock_price, cash):
having_stock = 0
left_cash = cash
for price in stock_price:
# 보유 현금으로 주식을 살 수 있다면
if left_cash >= price:
# 보유 주식은 몫을 담고
having_stock += left_cash // price
# 현금에는 나머지를 담는다
left_cash %= price
return having_stock * stock_price[-1] + left_cash
cash 변수를 훼손하지 않기 위해서 left_cash라는 변수를 이용해여 대신 사용한다. BNP(buy and pray)전략을 쓰는 준현이는 주식 매수 밖에 안하기 때문에 비교적 간단하게 구현할 수 있다. 매도에 대해서는 생각하지 않아도 됨다. 주식 값을 하나씩 확인하면서 주식을 살 수 있으면(보유 현금이 주식 값보다 크거나 같으면) 주식을 산다.
# 성민이의 주식 매도 매수
def timing(stock_price, cash):
having_stock = 0
left_cash = cash
# 성민이는 3일치의 데이터가 있어야 주식을 시작한다
for i in range(3, len(stock_price)):
action = what_to_do(stock_price, i)
if action == "buy":
if left_cash >= stock_price[i]:
having_stock += left_cash // stock_price[i]
left_cash %= stock_price[i]
if action == "sell":
if having_stock > 0:
left_cash += having_stock * stock_price[i]
having_stock = 0
return having_stock * stock_price[-1] + left_cash
이 두가지 경우만 구분해주면 된다. 그 역할을 what_to_do함수를 통해서 "sell"이나 "buy", "hold"라는 신호를 통해 확인할 수 있다. timing함수에서는 action변수에 what_to_do함수 리턴값을 받아서 저장하고, 조건문을 통해 상황에 맞게 처리한다.
*반복문을 i가 3일때부터 돌리는 이유는 성민이는 3일동안의 데이터가 쌓여야 주식을 시작하기 때문에 (i = 0~2)까지 3일동안은 what_to_do함수 및 매수, 매도를 하지 않기에 3부터 시작한다.
def what_to_do(stock_price, i):
if (stock_price[i-1] > stock_price[i-2] and stock_price[i-2] > stock_price[i-3]):
return "sell"
elif (stock_price[i-1] < stock_price[i-2] and stock_price[i-2] < stock_price[i-3]):
return "buy"
return "hold"
크게 설명할 부분은 없다. 3일치의 값을 비교해서 각 상황에 맞는 문자열을 리턴한다.