ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스] 주차 요금 계산 (2022 KAKAO BLIND RECRUITMENT) Swift
    알고리즘 2022. 9. 6. 23:31

    문제 내용

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

    여기서 읽어보세요잉

     

    제한사항

    • fees.count = 4
    • 1 ≤ records ≤ 1,000

    전체 코드

    import Foundation
    
    func solution(_ fees:[Int], _ records:[String]) -> [Int] {
        // 1
        var inTimes: [String: [Int]] = [:]
        var outTimes: [String: [Int]] = [:]
        var carNumbers: Set<String> = []
        
        // 2
        for record in records {
            let recordArr = record.split { $0 == " " }.map { String($0) }
            let carNumber = recordArr[1]
            let minute = parseTimeToMinute(recordArr[0])
            carNumbers.insert(carNumber)
            
            switch recordArr[2] {
            case "IN":
                var inTime = inTimes[carNumber] ?? []
                inTime.append(minute)
                inTimes[carNumber] = inTime
                
            case "OUT":
                var outTime = outTimes[carNumber] ?? []
                outTime.append(minute)
                outTimes[carNumber] = outTime
                
            default:
                break
            }
        }
        
        // 3
        return carNumbers
            .sorted(by: {
                return Int($0)! < Int($1)!
            })
            .compactMap { carNumber -> Int? in
                guard let inTime = inTimes[carNumber], inTime.isEmpty == false else { return nil }
                let outTime: [Int] = {
                    let times = outTimes[carNumber] ?? [parseTimeToMinute("23:59")]
                    return inTime.count == times.count ? times : times + [parseTimeToMinute("23:59")]
                }()
                return outTime.reduce(0, +) - inTime.reduce(0, +)
            }
            .map { time -> Int in
                  return time <= fees[0] ? fees[1] : fees[1] + Int(ceil(Double(time - fees[0]) / Double(fees[2]))) * fees[3]
            }
    }
    
    // 4
    func parseTimeToMinute(_ time: String) -> Int {
        let numbers = time.split { $0 == ":" }.map { Int($0)! }
        return numbers[0] * 60 + numbers[1]
    }

     

    

    // 1
    var inTimes: [String: [Int]] = [:]
    var outTimes: [String: [Int]] = [:]
    var carNumbers: Set<String> = []

    inTimes : 입차 시간 저장용, 차량 번호(String) 을 입력하여 입차 시간 배열 값을 얻어옴

    outTimes: 출차 시간 저장용, 차량 번호(String) 을 입력하여 출차 시간 배열 값을 얻어옴

    carNumbers: 차량 번호 저장용, Array 가 아닌 Set 으로 했음 (중복 저장X)

     

     

    // 2
    for record in records {
        let recordArr = record.split { $0 == " " }.map { String($0) }
        let carNumber = recordArr[1]
        let minute = parseTimeToMinute(recordArr[0])
        carNumbers.insert(carNumber)
    
        switch recordArr[2] {
        case "IN":
            var inTime = inTimes[carNumber] ?? []
            inTime.append(minute)
            inTimes[carNumber] = inTime
    
        case "OUT":
            var outTime = outTimes[carNumber] ?? []
            outTime.append(minute)
            outTimes[carNumber] = outTime
    
        default:
            break
        }
    }

     

    먼저 record 를 " " 로 쪼개서 차량 번호시간(parseTimeToMinute: 4번 섹션에 만들었음) 을 만들어줬음

    "IN" 일 때는 입차, "OUT" 일 때는 출차라서 해당하는 위치에 값을 저장했음 (1번 섹션의 inTimes 와 outTimes)

     

     

    // 3
    return carNumbers
        .sorted(by: {
            return Int($0)! < Int($1)! // 3-1
        })
        .compactMap { carNumber -> Int? in
            guard let inTime = inTimes[carNumber], inTime.isEmpty == false else { return nil }
            // 3-2
            let outTime: [Int] = {
                let times = outTimes[carNumber] ?? [parseTimeToMinute("23:59")]
                return inTime.count == times.count ? times : times + [parseTimeToMinute("23:59")]
            }()
            return outTime.reduce(0, +) - inTime.reduce(0, +)
        }
        .map { time -> Int in
              return time <= fees[0] ? fees[1] : fees[1] + Int(ceil(Double(time - fees[0]) / Double(fees[2]))) * fees[3]
        }

    먼저 저장된 차량 번호들은 정렬되지 않은 상태 (문제 정답이 차량 번호로 정렬된 순서임) 니까 sorted 를 이용해서 정렬했음

     

    3-1

    강제 언래핑 사용한 이유는 문제에서 0~9로 구성된 길이 4인 문자열이라 했음

     

    3-2

    compactMap 을 이용해 optional 값 처리했음 (여기도 강제 언래핑 해도 OK, 문제에 가능하다 적혀있음)

    먼저 차량 번호에 대한 입차 시간 값들: inTime 을 뽑아왔음

    두 번째로 출차 시간들을 가져오는데 만약 값이 없다면 입차 시간이 하나만 존재 (차량이 들어오기만 하고 나간 시간은 없는) 경우

    따라서 parseTimeToMinute("23:59") 를 outTime 으로 설정했음

    만약 입차 시간들과 출차 시간들의 수가 같다면 그대로 진행, 그렇지 않다면 마지막에 입차만하고 출차는 하지 않았다는 뜻이니까 parseTimeToMinute("23:59") 를 추가해줬음

    따라서 누적 주차 시간(분)총 출차 시간 값 - 총 입차 시간 값

     

    거기에 문제 조건에 따라 주차 요금을 계산 했음

     

     

    // 4
    func parseTimeToMinute(_ time: String) -> Int {
        let numbers = time.split { $0 == ":" }.map { Int($0)! }
        return numbers[0] * 60 + numbers[1]
    }

    문제 조건 ("HH":"MM") 에 따라 일단 ":" 로 쪼개고 numbers[0] (시간) 에 60 을 곱해서 분으로 만들고 numbers[1] (분) 도 더해줬음

     


    결론

    가독성 있게 문제 풀기 매우 어렵다.

     

    출처: 프로그래머스 2022 KAKAO BLIND RECRUITMENT 주차 요금 계산

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

     

Designed by Tistory.