iOS 개발 기록

Swift - 셔틀버스(프로그래머스, Lv3) 본문

코딩테스트

Swift - 셔틀버스(프로그래머스, Lv3)

택꽁이 2022. 5. 10. 22:12
728x90

문제 설명 

 

 

 

 

 

알고리즘

 풀이에 사용한 알고리즘의 의사코드. 

n의 범위가 1 이상, 10 이하이기 때문에 차량 시간대 별로 인원을 정리해두면 반복문을 10번만 돌려도 값을 구할 수 있었다. 

 

 

 

 

 

 

첫번째 코드 

import Foundation

func solution(_ n:Int, _ t:Int, _ m:Int, _ timetable:[String]) -> String {
    
    // 1. 차량 구하기
    var busTime = [Date]()
    for i in 1...n {
        busTime.append(busTimeTable(i, t))
    }
    
    // -> 막차보다 늦는 인원 자르고 계산
    var times = [Date]()
    timetable.forEach { if busTime.last! >= convertDate($0) {
        times.append(convertDate($0))
    }}
    times.sort()
    
    
    // 2. 차량 탑승 인원에 따라 경우 나눔.
    var peopleCount = pCount(busTime, times, m)
    var personCount = 0
    
//    print(peopleCount)
    
    for i in 0..<peopleCount.count {
        // 현재 탑승인원 초과하면 다음 차로 넘김
        if peopleCount[i] >= m {
            // 막차가 꽉 찬 경우 막차의 마지막 인원보다 1분 빠른 값 반환
            if i == peopleCount.count-1 {
                let index = personCount + m - 1
                return printDate(Date(timeInterval: -60, since: times[index]))
            } else {
                // 막차가 아닌 경우, 다음 차 탑승 인원 계산
                peopleCount[i+1] += (peopleCount[i] - m)
                personCount += m
            }
        } else {
            // 막차가 비어있으면 막차 탄다.
            if i == peopleCount.count-1 {
                return printDate(busTime[i])
            } else {
                // 앞에서부터 사람 수 체크
                personCount += peopleCount[i]
            }
        }
    }
    return ""
}

// 막차시간
func busTimeTable(_ n: Int, _ t: Int) -> Date {
    let intervalTime = (n-1) * t * 60
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "HH:mm"
    
    let start = dateFormatter.date(from: "09:00")!
    let last = Date(timeInterval: TimeInterval(intervalTime), since: start)
    
    return last
}


// 시간대별 탑승 인원 구하기
func pCount(_ busTime: [Date], _ peopleTime: [Date], _ m: Int) -> [Int] {
    var array = Array(repeating: 0, count: busTime.count)
    
    for time in peopleTime {
        for i in 0..<busTime.count {
            if time <= busTime[i] {
                array[i] += 1
                break
            }
        }
    }
    
    return array
}



// String -> Date 포맷으로 변환
func convertDate(_ str: String) -> Date {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "HH:mm"
    let date = dateFormatter.date(from: str)!

    return date
}


// Date -> String 포맷으로 변환
func printDate(_ date: Date) -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat  = "HH:mm"
    
    return dateFormatter.string(from: date)
}

 

통과 하기는 했는데  dateFormatter를 이용해 Date형으로 변환하여 계산했더니 계산 속도가 느렸다. 코딩테스트에서 Date는 사용하지 않는게 좋겠다.

 

 

 

 

두번째 코드 

import Foundation

func solution(_ n:Int, _ t:Int, _ m:Int, _ timetable:[String]) -> String {
    
    // 1. 차량 구하기
    let busTime = busTimeTable(n, t)
    let peopleTimeTable = people(timetable)

    // 2. 시간대별 탑승 인원 구하기
    var peopleCount = pCount(busTime, peopleTimeTable, m)
    var personCount = 0             // 막차 마지막 탑승 인원 index 파악하기 위한 변수
    
    
    for i in 0..<peopleCount.count {
        // 현재 탑승인원 초과하면 다음 차로 넘김
        if peopleCount[i] >= m {
            // 막차가 꽉 찬 경우 막차의 마지막 인원보다 1분 빠른 값 반환
            if i == peopleCount.count-1 {
                let index = personCount + m - 1

                return printTime(peopleTimeTable[index]-1)
            } else {
                // 막차가 아닌 경우, 다음 차 탑승 인원 계산
                peopleCount[i+1] += (peopleCount[i] - m)
                personCount += m
            }
        } else {
            // 막차가 비어있으면 막차 탄다.
            if i == peopleCount.count-1 {
                return printTime(busTime[i])
            } else {
                // 앞에서부터 사람 수 체크
                personCount += peopleCount[i]
            }
        }
    }
    
    return ""
}


// 버스시간표
func busTimeTable(_ n: Int, _ t: Int) -> [Int] {
    var time = [Int]()
    
    // 540은 첫 버스 시간 09:00를 분으로 계산한 것.
    for i in 0..<n {
        time.append(540 + (t * i))
    }
    
    return time
}



// 대기 시간 변환
func people(_ peopleTime: [String]) -> [Int] {
    var people = [Int]()
    peopleTime.forEach{ people.append(Int($0.prefix(2))! * 60 + Int($0.suffix(2))!) }
    people.sort()
    
    return people
}



// 시간대별 탑승 인원 구하기
func pCount(_ busTime: [Int], _ peopleTime: [Int], _ m: Int) -> [Int] {
    var array = Array(repeating: 0, count: busTime.count)
    
    for time in peopleTime {
        for i in 0..<busTime.count {
            if time <= busTime[i] {
                array[i] += 1
                break
            }
        }
    }
    
    return array
}

// 분을 시로 바꾸어 출력
func printTime(_ time: Int) -> String {
    let hour = String(time / 60).count == 1 ? "0\(String(time / 60))" : String(time / 60)
    let min = String(time % 60).count == 1 ? "0\(String(time % 60))" : String(time % 60)
    
    return "\(hour):\(min)"
}

 

똑같은 방법인데 시간만 Date가 아니라 Int형으로 계산했는데 속도의 향상이 엄청났다. 

 

 

 

 

배운점 

코테에 Date 쓰지마라 ...