Do.

2022 KAKAO BLIND RECRUITMENT - 주차요금 계산하기, Swift 본문

Algorithm

2022 KAKAO BLIND RECRUITMENT - 주차요금 계산하기, Swift

Hey_Hen 2022. 3. 14. 22:33

https://programmers.co.kr/learn/courses/30/lessons/92341?language=swift 

 

코딩테스트 연습 - 주차 요금 계산

[180, 5000, 10, 600] ["05:34 5961 IN", "06:00 0000 IN", "06:34 0000 OUT", "07:59 5961 OUT", "07:59 0148 IN", "18:59 0000 IN", "19:09 0148 OUT", "22:59 5961 IN", "23:00 5961 OUT"] [14600, 34400, 5000]

programmers.co.kr

1. 차량 출입과 그 시간을 계산하는게 핵심

2. 해당 차량의 총 주차장 이용 시간은 PlainTime(시:분 이 아니라 분으로 총 환산)만 계산해주면 어렵지 않다. 예를들어 6시 40분에 출입해서 7시 30분에 나갔다면 총 이용시간은 50분인데, 6시 40분을 PlainTime으로 환산하면 400분 과 같고, 7시 30분은 450분으로 결국 두 시각의 차이는 50분으로 동일하다.

 

 

 

import Foundation

final class ParkingTime: CustomStringConvertible {
  enum InOut {
    case `in`
    case out
  }

  private var currentInTime: Int = 0
  var totalUsedTime: Int = 0

  func setTime(_ time: String, type: InOut) {
    let plainTime = timeConvert(time)
    switch type {
      case .in:
        currentInTime = plainTime
      case .out:
        totalUsedTime += plainTime - currentInTime
        currentInTime = 0
    }
  }

  private func timeConvert(_ time: String) -> Int {
    let convert = time.components(separatedBy: ":")
    let hour = Int(convert[0])! * 60
    let minute = Int(convert[1])!
    return hour + minute
  }

  var description: String {
    totalUsedTime.description
  }
}

final class Parking {
  private var baseTime: Int = 0
  private var baseFee: Int = 0
  private var unitTime: Int = 0
  private var unitFee: Int = 0

  private var currentCarList: [String: ParkingTime] = [:]
  private var remain: Set<String> = []

  init() { }

  var feeList: [Int] {
    let sorted = currentCarList.sorted { lhs, rhs in
      lhs.key < rhs.key
    }

    return sorted.map {
      let totalTime = $0.value.totalUsedTime
      return feeCaculate(totalTime)
    }
  }

  private func feeCaculate(_ time: Int) -> Int {
    if time > baseTime {
      return baseFee + Int(ceil(Double(time - baseTime) / Double(unitTime))) * unitFee
    } else {
      return baseFee
    }
  }

  func setRecored(_ records: [String]) {
    records.forEach {
      let (time, carNumber, type) = recoredDecorder($0)
      if type == "IN" {
        remain.insert(carNumber)
      } else {
        remain.remove(carNumber)
      }
      if let car = currentCarList[carNumber] {
        car.setTime(time, type: type == "IN" ? .in : .out)
      } else {
        let parkingTime = ParkingTime()
        parkingTime.setTime(time, type: type == "IN" ? .in : .out)
        currentCarList[carNumber] = parkingTime
      }
    }

    remain.forEach { carNumber in
      guard let car = currentCarList[carNumber] else { return }
      car.setTime("23:59", type: .out)
    }
  }

  func setFees(_ fees: [Int]) {
    baseTime = fees[0]
    baseFee = fees[1]
    unitTime = fees[2]
    unitFee = fees[3]
  }

  private func recoredDecorder(_ record: String) -> (String, String, String) {
    let line = record.components(separatedBy: " ")
    return (line[0], line[1], line[2])
  }
}

func solution(_ fees:[Int], _ records:[String]) -> [Int] {

  let parking = Parking()
  parking.setFees(fees)
  parking.setRecored(records)

  return parking.feeList
}
Comments