본문 바로가기
코딩 테스트/백준

[백준] (Swift) 20546번 기적의 매매법

by Dev.Andy 2023. 5. 19.

머리말

이 문제를 선택한 이유 - 구현 문제 연습

앨런(Allan)과 하고 있는 디코 월목 스터디에서 이번 달에는 구현과 문자열에 집중해 보기 위해 택했다. 알고리즘에 대한 이론보다는 나의 사고 과정을 코드로 옮기는 연습이 필요한 시기였다.

문제 링크

20546번: 🐜 기적의 매매법 🐜

풀이

  1. 매매 전략이 두 개이기에 각 전략에 대한 함수가 필요해 보였다. 매개변수는 공통적으로 현재 남아 있는 현금(budget)과 주식 차트의 배열(stockChart)을 설정했다.
  2. 현재 주식의 가격은 주식 차트의 배열(stockChart)에서 인덱스로 접근하기로 했다.
  3. 각 전략에서 필요한 전량 매수와 전량 매도에 대한 함수를 각각 만들었다. 단순히 변수와 연산자로 구현할 수도 있겠지만, 함수의 가독성을 위해 언제 사고파는지를 구분하고 싶었다.
  4. 전량 매수는 필연적으로 몫과 나머지가 나오기에 튜플과 튜플의 요소의 이름을 활용했다.

코드

import Foundation

let budget = Int(readLine()!)!
let stockChart = readLine()!.split(separator: " ").map { Int($0)! }

if bnpStrategy(budget, stockChart) > timingStrategy(budget, stockChart) {
    print("BNP")
} else if bnpStrategy(budget, stockChart) < timingStrategy(budget, stockChart) {
    print("TIMING")
} else {
    print("SAMESAME")
}

func bnpStrategy(_ budget: Int, _ stockChart: [Int]) -> Int {
    var stockCount = 0
    var restBudget = budget

    for i in 0..<stockChart.count {
        if restBudget >= stockChart[i] {
            stockCount += buyStock(restBudget, stockChart[i]).stockCount
            restBudget = buyStock(restBudget, stockChart[i]).restBudget
        }
    }
    let lastDay = stockChart.count - 1
    let asset = restBudget + stockCount * stockChart[lastDay]
    
    return asset
}

func timingStrategy(_ budget: Int, _ stockChart: [Int]) -> Int {
    var stockCount = 0
    var restBudget = budget

    for i in 0..<stockChart.count - 3 {
        if (stockChart[i] < stockChart[i + 1] && stockChart[i + 1] < stockChart[i + 2] && stockChart[i + 2] < stockChart[i + 3]) {
            restBudget += sellStock(stockCount, stockChart[i + 3])
            stockCount = 0
        } else if (stockChart[i] > stockChart[i + 1] && stockChart[i + 1] > stockChart[i + 2] && stockChart[i + 2] > stockChart[i + 3]) {
            stockCount += buyStock(restBudget, stockChart[i + 3]).stockCount
            restBudget = buyStock(restBudget, stockChart[i + 3]).restBudget
        }
    }
    let lastDay = stockChart.count - 1
    let asset = restBudget + stockCount * stockChart[lastDay]
    
    return asset
}

func buyStock(_ budget: Int, _ stockPrice: Int) -> (stockCount: Int, restBudget: Int) {
    return (budget / stockPrice, budget % stockPrice)
}

func sellStock(_ stockCount: Int, _ stockPrice: Int) -> Int {
    return stockCount * stockPrice
}

 

꼬리말

후기

  • 알고리즘 자체는 어렵지는 않았지만 다뤄야하는 변수의 수가 많아서 이에 대한 효율적인 처리를 고민을 많이 해보게 된 문제였다.
  • 전량 매수와 전량 매도에 대한 함수를 추가적으로 정의하면서 괜히 내 코드가 더 복잡해지는 게 아닌가 하는 생각이 들었다. 특히나 전량 매수 함수(buyStock)에서 반환값으로 튜플을 사용하면서 더욱 그랬다.
  • 조건문의 길이가 너무 길어져서 보기도 지저분하고 한 줄을 넘기는 게 보기가 불편했다. 좀 더 효율적인 코드가 없을까?

댓글