HIT해

[Swift/프로그래머스] 과제 진행하기 (?) 본문

Swift/Swift 알고리즘

[Swift/프로그래머스] 과제 진행하기 (?)

힛해 2024. 11. 1. 00:37
728x90

https://school.programmers.co.kr/learn/courses/30/lessons/176962

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

시간을 계산할때 : 을 기준으로 split을 해준뒤 시간에는 60을 곱해서 계산하는 방식을 사용했었는데

 

DateFormatter()를 사용해서 날짜를 계산하고 싶었다.

 

처음 풀이

import Foundation
func solution(_ plans:[[String]]) -> [String] {
   // 가장 최근에 멈춰둔 과제니까 stack
   // Swift는 사실 상관없음
   
   let dateFormatter = DateFormatter()
   dateFormatter.dateFormat = "HH:mm"
   
   var wait = [(String,Int)]()
   var answer = [String]()
   
   
   let sortedPlans = plans.sorted { 
      dateFormatter.date(from: $0[1])! < dateFormatter.date(from: $1[1])! 
  }

  var cutLine : Date?
    
  for (index,plan) in sortedPlans.enumerated() {
      // 시작하는 시간
      let currentPlanTime = dateFormatter.date(from:plan[1])!
      
      // 끝나는 시간
      let currentTimeAfter = Calendar.current.date(byAdding: .minute, value : Int(plan[2]) ?? 0, to : currentPlanTime)!
      
      // 다음 일정 
      if index+1 < sortedPlans.count {
         cutLine = dateFormatter.date(from:sortedPlans[index+1][1])
          
         // 수행 가능한 경우
         if let cutLine = cutLine, cutLine >= currentTimeAfter{
             answer.append(plan[0])
             
             // 다음 시작 시간까지 남은 시간
             var remainTime = Int(cutLine.timeIntervalSince(currentTimeAfter) / 60)
             while !wait.isEmpty && remainTime > 0 {
                let last = wait.removeLast()
                if remainTime >= last.1 {
                    remainTime -= last.1
                    answer.append(last.0)
                }else{
                    wait.append((last.0,last.1 - remainTime))
                    remainTime = 0
                }
             }
         }
          // 수행 불가능한 경우
          else{
             let remainTime = Int(plan[2])! - Int(cutLine!.timeIntervalSince(currentPlanTime) / 60)
                 wait.append((plan[0], remainTime))
         }
          
          
          
          
      }
      // 마지막 일정이라면 계산없이 바로 추가.
      else{
          answer.append(plan[0])
      }
      
  }

  while !wait.isEmpty {
      let plan = wait.popLast()!
      answer.append(plan.0)
  }
    
  return answer
}

 

 

Date를 연산하는 과정에서 시간초과가 발생했다

 

개선한 코드

import Foundation
func solution(_ plans:[[String]]) -> [String] {
   let dateFormatter = DateFormatter()
   dateFormatter.dateFormat = "HH:mm"
   
   var wait = [(String,Int)]()
   var answer = [String]()
   
   let sortedPlans = plans.sorted { 
      dateFormatter.date(from: $0[1])! < dateFormatter.date(from: $1[1])! 
  }
    
  for (index,plan) in sortedPlans.enumerated() {
      // 시작하는 시간
      let currentPlanTime = dateFormatter.date(from:plan[1])!
      let duration = Int(plan[2])!
      
      // 다음 일정 
      if index+1 < sortedPlans.count {
         let nextStartTime = dateFormatter.date(from:sortedPlans[index+1][1])!
         let timeUntilNext = Int(nextStartTime.timeIntervalSince(currentPlanTime) / 60)
         
         // 수행 가능한 경우
         if timeUntilNext >= duration {
             answer.append(plan[0])
             
             // 다음 시작 시간까지 남은 시간
             var remainTime = timeUntilNext - duration
             while !wait.isEmpty && remainTime > 0 {
                let last = wait.removeLast()
                if remainTime >= last.1 {
                    remainTime -= last.1
                    answer.append(last.0)
                } else {
                    wait.append((last.0, last.1 - remainTime))
                    break
                }
             }
         }
         // 수행 불가능한 경우
         else {
             wait.append((plan[0], duration - timeUntilNext))
         }
      }
      // 마지막 일정이라면 계산없이 바로 추가
      else {
          answer.append(plan[0])
      }
  }
  
  while !wait.isEmpty {
      let plan = wait.popLast()!
      answer.append(plan.0)
  }
    
  return answer
}

 

Date 객체 생성 부분

 

// 변경 전
let currentTimeAfter = Calendar.current.date(byAdding: .minute, value : Int(plan[2]) ?? 0, to : currentPlanTime)!
cutLine = dateFormatter.date(from:sortedPlans[index+1][1])

 

// 변경 후
let duration = Int(plan[2])!
let nextStartTime = dateFormatter.date(from:sortedPlans[index+1][1])!
let timeUntilNext = Int(nextStartTime.timeIntervalSince(currentPlanTime) / 60)

 

// 변경 후
if timeUntilNext >= duration {
// 변경 후
var remainTime = timeUntilNext - duration

 

시간과 시간을 비교하는게 아닌 남은 시간과 남은 시간을 비교해 Date Date 비교가 아닌 Int끼리의 비교로 시간을 단축시켰다.