[BOJ_Python] 20546번 기적의 매매법 (브론즈 5)

황준성·2024년 10월 24일
0

BOJ_Python

목록 보기
2/70

문제 20546번

https://www.acmicpc.net/problem/20546

이번 문제는 구현하는데 크게 어려움이 없었다. 백준 기준 실버5 문제이다보니 그런 것 같다.


예제 입력 1

100
10 20 23 34 55 30 22 19 12 45 23 44 34 38

예제 출력 1

BNP
  • 준현이는 1월 1일에 10주를 매수한다. 따라서 1월 14일 380원의 자산을 가지게 된다.

  • 성민이는 1월 8일에 5주를 매수한다. 따라서 1월 14일 195원의 자산을 가지게 된다.

예제 입력 2

15
20 20 33 98 15 6 4 1 1 1 2 3 6 14

예제 출력 2

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")

풀이 설명

사용자 정의 함수 BNP - 준현이

# 준현이의 주식 매도 매수
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)전략을 쓰는 준현이는 주식 매수 밖에 안하기 때문에 비교적 간단하게 구현할 수 있다. 매도에 대해서는 생각하지 않아도 됨다. 주식 값을 하나씩 확인하면서 주식을 살 수 있으면(보유 현금이 주식 값보다 크거나 같으면) 주식을 산다.

  • having_stock에는 나누어진 몫을 더해주고, left_cash에는 나눈 나머지를 대입해준다.

사용자 정의 함수 TIMING - 성민이

# 성민이의 주식 매도 매수
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

성민이의 경우에는 몇가지 신경써야 할 부분이 있다.

  • 주식을 사는 경우 - 주식이 연속적으로 3일 동안 떨어지면 4일차에 주식을 산다.
  • 주식을 파는 경우 - 주식이 연속적으로 3일 동안 올라가면 4일차에 주식을 판다.

이 두가지 경우만 구분해주면 된다. 그 역할을 what_to_do함수를 통해서 "sell"이나 "buy", "hold"라는 신호를 통해 확인할 수 있다. timing함수에서는 action변수에 what_to_do함수 리턴값을 받아서 저장하고, 조건문을 통해 상황에 맞게 처리한다.

*반복문을 i가 3일때부터 돌리는 이유는 성민이는 3일동안의 데이터가 쌓여야 주식을 시작하기 때문에 (i = 0~2)까지 3일동안은 what_to_do함수 및 매수, 매도를 하지 않기에 3부터 시작한다.

what_to_do 함수

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일치의 값을 비교해서 각 상황에 맞는 문자열을 리턴한다.

profile
Make progress

0개의 댓글