문제 설명

레스토랑을 운영하던 스카피는 코로나19로 인한 불경기를 극복하고자 메뉴를 새로 구성하려고 고민하고 있습니다.
기존에는 단품으로만 제공하던 메뉴를 조합해서 코스요리 형태로 재구성해서 새로운 메뉴를 제공하기로 결정했습니다. 어떤 단품메뉴들을 조합해서 코스요리 메뉴로 구성하면 좋을 지 고민하던 "스카피"는 이전에 각 손님들이 주문할 때 가장 많이 함께 주문한 단품메뉴들을 코스요리 메뉴로 구성하기로 했습니다.
단, 코스요리 메뉴는 최소 2가지 이상의 단품메뉴로 구성하려고 합니다. 또한, 최소 2명 이상의 손님으로부터 주문된 단품메뉴 조합에 대해서만 코스요리 메뉴 후보에 포함하기로 했습니다.

예를 들어, 손님 6명이 주문한 단품메뉴들의 조합이 다음과 같다면,
(각 손님은 단품메뉴를 2개 이상 주문해야 하며, 각 단품메뉴는 A ~ Z의 알파벳 대문자로 표기합니다.)

가장 많이 함께 주문된 단품메뉴 조합에 따라 "스카피"가 만들게 될 코스요리 메뉴 구성 후보는 다음과 같습니다.

[문제]

각 손님들이 주문한 단품메뉴들이 문자열 형식으로 담긴 배열 orders, "스카피"가 추가하고 싶어하는 코스요리를 구성하는 단품메뉴들의 갯수가 담긴 배열 course가 매개변수로 주어질 때, "스카피"가 새로 추가하게 될 코스요리의 메뉴 구성을 문자열 형태로 배열에 담아 return 하도록 solution 함수를 완성해 주세요.

[제한사항]

  • orders 배열의 크기는 2 이상 20 이하입니다.
  • orders 배열의 각 원소는 크기가 2 이상 10 이하인 문자열입니다.
    • 각 문자열은 알파벳 대문자로만 이루어져 있습니다.
    • 각 문자열에는 같은 알파벳이 중복해서 들어있지 않습니다.
  • course 배열의 크기는 1 이상 10 이하입니다.
    • course 배열의 각 원소는 2 이상 10 이하인 자연수가 오름차순으로 정렬되어 있습니다.
    • course 배열에는 같은 값이 중복해서 들어있지 않습니다.
  • 정답은 각 코스요리 메뉴의 구성을 문자열 형식으로 배열에 담아 사전 순으로 오름차순 정렬해서 return 해주세요.
    • 배열의 각 원소에 저장된 문자열 또한 알파벳 오름차순으로 정렬되어야 합니다.
    • 만약 가장 많이 함께 주문된 메뉴 구성이 여러 개라면, 모두 배열에 담아 return 하면 됩니다.
    • orders와 course 매개변수는 return 하는 배열의 길이가 1 이상이 되도록 주어집니다.

내가 푼 풀이

- 1번 손님이 ABCFG 를 주문했다면 2개 요리의 코스메뉴는 AB, AC, AF, AG, BC, ... , FG 이다.

- 코스요리의 음식갯수대로 문자조합을 추출해서 Dictionary에 저장한다.

- 이미 앞손님이 시켰다면 ( dict[a] != nil ) +1 을 더해주고, 시키지 않았다면 초기화를 해준다.

- 주문들의 문자 조합을 모두 완성하고, value의 최댓값인 key를 결과배열에 저장한다. 

- value 가 최댓값이지만 1이라면 한 손님만 시킨 음식조합이므로 결과배열에 넣지않는다.

- 결과배열을 오름차순으로 정렬해서 출력한다.

- 조합은 Swift에서 제공하지않아서, 직접 구현할 줄 알아야한다.

 

import Foundation

func combi (_ strs: [String], _ count: Int) -> [[String]] {
    var result = [[String]]()
    
    func combination(_ index: Int, _ nowCombi: [String]) {
        if nowCombi.count == count {
            result.append(nowCombi)
            return
        }
        for i in index..<strs.count {
            combination(i+1, nowCombi + [strs[i]])
        }
    }
    combination(0, [])
    
    return result
}

func solution(_ orders:[String], _ course:[Int]) -> [String] {
    var result = [String]()
    
    for i in course {
        var dict = [String: Int]()
        var count = i
        
        for j in orders {
            var arr = String(j).map{String($0)}
            var combiArr = combi(arr, count)
            for k in combiArr {
                var str = k.sorted{$0 < $1}.joined(separator: "")
                if dict[str] == nil {
                    dict[str] = 1
                } else {
                    dict[str]! += 1
                }
            }  
        }
        
        var sortedDict = dict.sorted{ $0.value > $1.value}
        
        if dict.values.max() == nil {
            continue
        } else {
            for (key, value) in sortedDict {
                if value == dict.values.max()! && value != 1 {
                    result.append(key)
                } else {
                    break
                }
            }
        }
    }
    return result.sorted{ $0 < $1}
}

문제 설명

철수는 롤케이크를 두 조각으로 잘라서 동생과 한 조각씩 나눠 먹으려고 합니다. 이 롤케이크에는 여러가지 토핑들이 일렬로 올려져 있습니다. 철수와 동생은 롤케이크를 공평하게 나눠먹으려 하는데, 그들은 롤케이크의 크기보다 롤케이크 위에 올려진 토핑들의 종류에 더 관심이 많습니다. 그래서 잘린 조각들의 크기와 올려진 토핑의 개수에 상관없이 각 조각에 동일한 가짓수의 토핑이 올라가면 공평하게 롤케이크가 나누어진 것으로 생각합니다.

예를 들어, 롤케이크에 4가지 종류의 토핑이 올려져 있다고 합시다. 토핑들을 1, 2, 3, 4와 같이 번호로 표시했을 때, 케이크 위에 토핑들이 [1, 2, 1, 3, 1, 4, 1, 2] 순서로 올려져 있습니다. 만약 세 번째 토핑(1)과 네 번째 토핑(3) 사이를 자르면 롤케이크의 토핑은 [1, 2, 1], [3, 1, 4, 1, 2]로 나뉘게 됩니다. 철수가 [1, 2, 1]이 놓인 조각을, 동생이 [3, 1, 4, 1, 2]가 놓인 조각을 먹게 되면 철수는 두 가지 토핑(1, 2)을 맛볼 수 있지만, 동생은 네 가지 토핑(1, 2, 3, 4)을 맛볼 수 있으므로, 이는 공평하게 나누어진 것이 아닙니다. 만약 롤케이크의 네 번째 토핑(3)과 다섯 번째 토핑(1) 사이를 자르면 [1, 2, 1, 3], [1, 4, 1, 2]로 나뉘게 됩니다. 이 경우 철수는 세 가지 토핑(1, 2, 3)을, 동생도 세 가지 토핑(1, 2, 4)을 맛볼 수 있으므로, 이는 공평하게 나누어진 것입니다. 공평하게 롤케이크를 자르는 방법은 여러가지 일 수 있습니다. 위의 롤케이크를 [1, 2, 1, 3, 1], [4, 1, 2]으로 잘라도 공평하게 나뉩니다. 어떤 경우에는 롤케이크를 공평하게 나누지 못할 수도 있습니다.

롤케이크에 올려진 토핑들의 번호를 저장한 정수 배열 topping이 매개변수로 주어질 때, 롤케이크를 공평하게 자르는 방법의 수를 return 하도록 solution 함수를 완성해주세요.


제한사항
  • 1 ≤ topping의 길이 ≤ 1,000,000
    • 1 ≤ topping의 원소 ≤ 10,000

내가 푼 풀이

- topping의 길이가 최대 1,000,000 이라서 2중 for문은 무조건 시간초과가 뜰꺼라 생각했다.

- 처음에는 for문으로 topping[0...i] 와 topping[i+1..<topping.count] 두 배열을 Set으로 만들어 중복을 제거하고 갯수 확인으로 검사했다. ----> 역시나 시간초과

- Dictionary[Int: Int] 로 처음에 총 토핑과 토핑의갯수를 구했다.

- 배열의 앞부터 잘라서 넣어놓을 Set 하나를 선언해두고 배열을 순회할때마다 잘라서 Set에 넣어주고 Dictionary에는 토핑과 그토핑의 갯수를 빼줬다.

- Dictionary에 만약 토핑의 갯수가 0 이라면 지우고, Dictionary의 갯수와 Set의 갯수가 같으면 공평하다 -> result += 1

- result 출력

 

 

import Foundation

func solution(_ topping:[Int]) -> Int {
    var result = 0
    var arr = topping
    var set1 = Set<Int>()
    var dict = [Int: Int]()
    for i in 0..<topping.count {
        if dict[topping[i]] == nil {
            dict[topping[i]] = 1
        } else {
            dict[topping[i]]! += 1
        }
    }
    for i in 0..<topping.count {
        set1.insert(topping[i])
        dict[topping[i]]! -= 1
        if dict[topping[i]]! == 0 {
            dict[topping[i]] = nil
        }
        if set1.count == dict.count {
            result += 1
        }
    }

    return result
}

문제 설명

자연수 x를 y로 변환하려고 합니다. 사용할 수 있는 연산은 다음과 같습니다.

  • x에 n을 더합니다
  • x에 2를 곱합니다.
  • x에 3을 곱합니다.

자연수 x, y, n이 매개변수로 주어질 때, x를 y로 변환하기 위해 필요한 최소 연산 횟수를 return하도록 solution 함수를 완성해주세요. 이때 x를 y로 만들 수 없다면 -1을 return 해주세요.


제한사항
  • 1 ≤ x  y ≤ 1,000,000
  • 1 ≤ n < y

내가 푼 풀이

- 모든 경우의 수를 구하는 방식으로 중복을 제거하는 Set 안에 연산한 결과를 전부 넣었다.

- 넣을 수 없는경우 -1을 출력한다.

- dp방법도 있는데 나중에 풀어봐야겠다..

 

 

import Foundation

func solution(_ x:Int, _ y:Int, _ n:Int) -> Int {
    var numSet = Set([x])
    var result = 0
    
    while true {
        var addSet = Set<Int>()
        if numSet.contains(y) {
            return result
        }
        for i in numSet {
            if i+n <= y {
                addSet.insert(i+n)
            }
            if i*2 <= y {
                addSet.insert(i*2)
            }
            if i*3 <= y {
                addSet.insert(i*3)
            }
        }
        numSet  = addSet
        result += 1
        if numSet.isEmpty {
            break
        }
    }

    return -1
}

 

 

< DP 풀이>

Array의 크기: y+1, 배열의 원소를 모두 Int의 최댓값으로 선언

시작점 x 의 arr[x] = 0

세가지 연산 x+n , x*2 , x*3 수행후 y보다 같거나 작으면 

  •  x+n <= y : arr[x+n] = min(arr[x]+1, arr[x+n])
  •  x * 2 <= y : arr[x+n] = min(arr[x]+1, arr[x+n])
  •  x * 3 <= y : arr[x+n] = min(arr[x]+1, arr[x+n])

최소 연산횟수를 구해야하므로 min 적용한다.

결과: arr[y] : 만약 세가지 연산으로 arr[y] 의 값을 변경하지 못했다면 arr[y] = Int.max

 

import Foundation

func solution(_ x:Int, _ y:Int, _ n:Int) -> Int {
    var arr = Array(repeating: Int.max, count: y+1)
    arr[x] = 0
    
    for i in x...y where arr[i] != Int.max {
        if i+n <= y {
            arr[i+n] = min(arr[i] + 1, arr[i+n])
        }
        if i*2 <= y {
            arr[i*2] = min(arr[i] + 1, arr[i*2])
        }
        if i*3 <= y {
            arr[i*3] = min(arr[i] + 1, arr[i*3])
        }
    }
    if arr[y] == Int.max {
        return -1
    } else {
        return arr[y]
    }
}

문제 설명

0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.

예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.

0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요.

제한 사항
  • numbers의 길이는 1 이상 100,000 이하입니다.
  • numbers의 원소는 0 이상 1,000 이하입니다.
  • 정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.

내가 푼 풀이

- 주어진 정수를 문자열 배열로 만든다.

- 두개의 문자열을 비교했을때 문자가 큰것은 사전순으로 뒤에 온다는 뜻이다.

- 두개의 문자열 s1 , s2 가 s1 +s2 > s2 + s1 은 문자열 두개를 합쳐서 정수로 비교했을때, s1+s2 가 더 큰 값이다.

- 배열내에 모든 문자열을 sorted 함수를 이용해서 정수로 비교했을때 큰경우로 정렬한다.

 

sorted{ return $0 + $1 > $1 + $0} 실행과정

예제 배열 [3, 30, 34, 5, 9]  // print("true \($0) \($1)") , print("false \($1) \($0)")

 

import Foundation

func solution(_ numbers:[Int]) -> String {
    var arr = numbers.map{String($0)}
    var sortedArr = arr.sorted{ return $0 + $1 > $1 + $0 }
    if sortedArr.filter{$0 == "0"}.count == sortedArr.count {
        return "0"
    } else {
        return sortedArr.joined(separator: "")
    }
}

문제 설명

정수로 이루어진 배열 numbers가 있습니다. 배열 의 각 원소들에 대해 자신보다 뒤에 있는 숫자 중에서 자신보다 크면서 가장 가까이 있는 수를 뒷 큰수라고 합니다.
정수 배열 numbers가 매개변수로 주어질 때, 모든 원소에 대한 뒷 큰수들을 차례로 담은 배열을 return 하도록 solution 함수를 완성해주세요. 단, 뒷 큰수가 존재하지 않는 원소는 -1을 담습니다.


제한사항
  • 4 ≤ numbers의 길이 ≤ 1,000,000
    • 1 ≤ numbers[i] ≤ 1,000,000

내가 푼 풀이

- numbers의 길이 최댓값이 1,000,000 이다.

- 단순히 2중 for문으로 인덱스 i 보다 뒤에있는 큰 숫자를 찾게하더니 테스트 20부터 싸그리 시간초과가 떴다.

- 검사할 원소보다 뒤에 있으면서 커야한다.

- 스택을 사용해서 차곡차곡넣으면 가장 윗부분이 검사할 원소와 가장 가까운 원소다.

- numbers 배열을 정순으로 가면 스택을 이용할 그림이 안나와서 역순으로 돌렸다.

- 스택 배열이 비어있으면 추가하고 -1, 매번 검사할때마다 스택을 pop해서 비교한다.

 

 

import Foundation

func solution(_ numbers:[Int]) -> [Int] {
    var arr = [Int]()
    var result = [Int]()
    var num = 0
    
    for i in numbers.reversed() {
        if arr.count == 0 {
            arr.append(i)
            result.append(-1)
        } else {
            num = arr.popLast()!
            while num <= i && arr.count > 0 {
                num = arr.popLast()!
            }
            if num > i {
                result.append(num)
                arr.append(num)
                arr.append(i)
            } else {
                if arr.count == 0 {
                    result.append(-1)
                    arr.append(i)
                }
            }
        }
        
    }

    return result.reversed()
}

프렌즈4블록

블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 "프렌즈4블록".
같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙어있을 경우 사라지면서 점수를 얻는 게임이다.

만약 판이 위와 같이 주어질 경우, 라이언이 2×2로 배치된 7개 블록과 콘이 2×2로 배치된 4개 블록이 지워진다. 같은 블록은 여러 2×2에 포함될 수 있으며, 지워지는 조건에 만족하는 2×2 모양이 여러 개 있다면 한꺼번에 지워진다.

블록이 지워진 후에 위에 있는 블록이 아래로 떨어져 빈 공간을 채우게 된다.

만약 빈 공간을 채운 후에 다시 2×2 형태로 같은 모양의 블록이 모이면 다시 지워지고 떨어지고를 반복하게 된다.

위 초기 배치를 문자로 표시하면 아래와 같다.

TTTANT
RRFACC
RRRFCC
TRRRAA
TTMMMF
TMMTTJ

각 문자는 라이언(R), 무지(M), 어피치(A), 프로도(F), 네오(N), 튜브(T), 제이지(J), 콘(C)을 의미한다

입력으로 블록의 첫 배치가 주어졌을 때, 지워지는 블록은 모두 몇 개인지 판단하는 프로그램을 제작하라.

입력 형식

  • 입력으로 판의 높이 m, 폭 n과 판의 배치 정보 board가 들어온다.
  • 2 ≦ n, m ≦ 30
  • board는 길이 n인 문자열 m개의 배열로 주어진다. 블록을 나타내는 문자는 대문자 A에서 Z가 사용된다.

출력 형식

입력으로 주어진 판 정보를 가지고 몇 개의 블록이 지워질지 출력하라.

 

내가 푼 풀이

- 주어진 문자열을 2차원 배열로 만든다.

- 2중 for문으로 원소 하나가 오른쪽, 왼쪽, 오른쪽대각선이 랑 모두같은지 확인한다.

- 모두 같으면 같은 4개의 x,y 위치를 저장한다.

- 이미 저장되있는경우 스킵하고 저장한다

- 저장된 배열을 순회해서 값을 "0"으로 만든다.

- 2차원 배열 보드의 맨 아래부터 빈곳을 확인해서 위에서 아래로 내려준다.

- 이 과정을 반복해서 원소가 같은 4개의 위치가 없는 경우 반복 탈출하고 갯수를 출력한다.

 

 

func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
    var gameBoard = [[String]]()
    var removeArr = [[Int]]()
    var isEnd = true
    
    for i in board {    // 주어진 문자열을 2차원배열로 만든다.
        gameBoard.append(i.map{String($0)})
    }
    
    while isEnd {
        var removing = [[Int]]()
        
        for i in 0..<m-1 {  // 2x2를 찾기위해 y의 길이-1까지 탐색
            for j in 0..<n-1 { // 2x2를 찾기위해 y의 길이-1까지 탐색
                var str = gameBoard[i][j]
                if str == "0" { // 이미 소거된경우 패스
                    continue
                }
                var arr = [gameBoard[i][j], gameBoard[i+1][j], gameBoard[i][j+1], gameBoard[i+1][j+1]]
                if arr.filter{ $0 == str }.count == 4 { //  2x2가 모두 같은원소인경우
                    var addSet = [[i, j], [i, j+1], [i+1, j], [i+1, j+1]]
                    for k in addSet {   // x,y위치가 저장되있는 2차원배열에 같은 위치인경우 패스
                        if removing.contains(k) {
                            continue
                        }
                        removing.append(k)
                    }
                }
            }
        }
        
        if removing.isEmpty {   // 더이상 같은 2x2가 없는경우
            break
        } else {
            removeArr += removing   // 2x2의 원소갯수 저장 (x,y 인덱스)
            for i in removing {     // 같은 2x2 위치를 0으로 제거
                gameBoard[i[0]][i[1]] = "0"
            }
        }
        
        for i in 1..<m {    // 중간에 제거된경우 위에서 아래로 내려주기
            for j in 0..<n {
                var xIdx = m-i
                if gameBoard[xIdx][j] == "0" {  
                    var idx = xIdx
                    while gameBoard[xIdx][j] == "0" && xIdx > 0 {  //제거된곳보다 위에있는 제거되지않은 원소 찾기
                        xIdx -= 1
                    }
                    gameBoard[idx][j] = gameBoard[xIdx][j]
                    gameBoard[xIdx][j] = "0"
                }
            }
        }
        
    }

    return removeArr.count
}

문제 설명

파일명 정렬

세 차례의 코딩 테스트와 두 차례의 면접이라는 기나긴 블라인드 공채를 무사히 통과해 카카오에 입사한 무지는 파일 저장소 서버 관리를 맡게 되었다.

저장소 서버에는 프로그램의 과거 버전을 모두 담고 있어, 이름 순으로 정렬된 파일 목록은 보기가 불편했다. 파일을 이름 순으로 정렬하면 나중에 만들어진 ver-10.zip이 ver-9.zip보다 먼저 표시되기 때문이다.

버전 번호 외에도 숫자가 포함된 파일 목록은 여러 면에서 관리하기 불편했다. 예컨대 파일 목록이 ["img12.png", "img10.png", "img2.png", "img1.png"]일 경우, 일반적인 정렬은 ["img1.png", "img10.png", "img12.png", "img2.png"] 순이 되지만, 숫자 순으로 정렬된 ["img1.png", "img2.png", "img10.png", img12.png"] 순이 훨씬 자연스럽다.

무지는 단순한 문자 코드 순이 아닌, 파일명에 포함된 숫자를 반영한 정렬 기능을 저장소 관리 프로그램에 구현하기로 했다.

소스 파일 저장소에 저장된 파일명은 100 글자 이내로, 영문 대소문자, 숫자, 공백(" "), 마침표("."), 빼기 부호("-")만으로 이루어져 있다. 파일명은 영문자로 시작하며, 숫자를 하나 이상 포함하고 있다.

파일명은 크게 HEAD, NUMBER, TAIL의 세 부분으로 구성된다.

  • HEAD는 숫자가 아닌 문자로 이루어져 있으며, 최소한 한 글자 이상이다.
  • NUMBER는 한 글자에서 최대 다섯 글자 사이의 연속된 숫자로 이루어져 있으며, 앞쪽에 0이 올 수 있다. 0부터 99999 사이의 숫자로, 00000이나 0101 등도 가능하다.
  • TAIL은 그 나머지 부분으로, 여기에는 숫자가 다시 나타날 수도 있으며, 아무 글자도 없을 수 있다.

파일명을 세 부분으로 나눈 후, 다음 기준에 따라 파일명을 정렬한다.

  • 파일명은 우선 HEAD 부분을 기준으로 사전 순으로 정렬한다. 이때, 문자열 비교 시 대소문자 구분을 하지 않는다. MUZI와 muzi, MuZi는 정렬 시에 같은 순서로 취급된다.
  • 파일명의 HEAD 부분이 대소문자 차이 외에는 같을 경우, NUMBER의 숫자 순으로 정렬한다. 9 < 10 < 0011 < 012 < 13 < 014 순으로 정렬된다. 숫자 앞의 0은 무시되며, 012와 12는 정렬 시에 같은 같은 값으로 처리된다.
  • 두 파일의 HEAD 부분과, NUMBER의 숫자도 같을 경우, 원래 입력에 주어진 순서를 유지한다. MUZI01.zip과 muzi1.png가 입력으로 들어오면, 정렬 후에도 입력 시 주어진 두 파일의 순서가 바뀌어서는 안 된다.

무지를 도와 파일명 정렬 프로그램을 구현하라.

입력 형식

입력으로 배열 files가 주어진다.

  • files는 1000 개 이하의 파일명을 포함하는 문자열 배열이다.
  • 각 파일명은 100 글자 이하 길이로, 영문 대소문자, 숫자, 공백(" "), 마침표("."), 빼기 부호("-")만으로 이루어져 있다. 파일명은 영문자로 시작하며, 숫자를 하나 이상 포함하고 있다.
  • 중복된 파일명은 없으나, 대소문자나 숫자 앞부분의 0 차이가 있는 경우는 함께 주어질 수 있다. (muzi1.txt, MUZI1.txt, muzi001.txt, muzi1.TXT는 함께 입력으로 주어질 수 있다.)

출력 형식

위 기준에 따라 정렬된 배열을 출력한다.

 

내가 푼 풀이

- TAIL 은 정렬할때 필요가 없으므로, Dictionary(String: [String]]을 선언한다.

- HEAD, NUMBER, 입력순서 세가지를 저장한다.

- 저장할때 HEAD는 첫글자부터 숫자를 만나기전까지, NUMBER은 숫자를 만나서 만나지 않을때까지 순회하면서 저장시킨다.

- 저장된 HEAD, NUMBER 을 문자열로 만들어 Dictionary에 저장한다.

- 3가지 정렬대로 정렬한다. ( 1. HEAD 사전순 2. NUMBER 크기순 3. 입력순서)

- 아예 역순으로 1번 사전순이 같고, 2번 크기가 같으면 입력순서대로, 1번사전순만 같으면 2번 크기순으로, 1번 사전순이 다르면 사전순으로 정렬하게끔 코딩한다.

 

func solution(_ files:[String]) -> [String] {
    var dict = [String: [String]]()
    var result = [String]()
    var idx = 0
    for i in files {
        var arr = i.map{ String($0)}
        var head = [String]()
        var number = [String]()
        
        var headEnd = false
        var numEnd = false
        
        for j in 0..<arr.count {
            if !headEnd {
                if Int(arr[j]) == nil {
                    head.append(arr[j])
                } else {
                    number.append(arr[j])
                    headEnd = true
                }
            } else if !numEnd {
                if Int(arr[j]) != nil {
                    number.append(arr[j])
                } else {
                    break
                }
            }
        }
        dict[String(i)] = [head.joined(separator: ""), number.joined(separator: ""), String(idx)]
        idx += 1
    }
    var sortedDict = dict.sorted{if $0.value[0].uppercased() == $1.value[0].uppercased() {
        if Int($0.value[1]) == Int($1.value[1]) {
            return Int($0.value[2])! < Int($1.value[2])!
        } else {
            return Int($0.value[1])! < Int($1.value[1])!
        }
    } else { return $0.value[0].uppercased() < $1.value[0].uppercased() }}
    for i in sortedDict {
        result.append(i.key)
    }

    return result
}

문제 설명

문제 설명

주차장의 요금표와 차량이 들어오고(입차) 나간(출차) 기록이 주어졌을 때, 차량별로 주차 요금을 계산하려고 합니다. 아래는 하나의 예시를 나타냅니다.

  • 요금표

  • 입/출차 기록

  • 자동차별 주차 요금

  • 어떤 차량이 입차된 후에 출차된 내역이 없다면, 23:59에 출차된 것으로 간주합니다.
    • 0000번 차량은 18:59에 입차된 이후, 출차된 내역이 없습니다. 따라서, 23:59에 출차된 것으로 간주합니다.
  • 00:00부터 23:59까지의 입/출차 내역을 바탕으로 차량별 누적 주차 시간을 계산하여 요금을 일괄로 정산합니다.
  • 누적 주차 시간이 기본 시간이하라면, 기본 요금을 청구합니다.
  • 누적 주차 시간이 기본 시간을 초과하면, 기본 요금에 더해서, 초과한 시간에 대해서 단위 시간 마다 단위 요금을 청구합니다.
    • 초과한 시간이 단위 시간으로 나누어 떨어지지 않으면, 올림합니다.
    • ⌈a⌉ : a보다 작지 않은 최소의 정수를 의미합니다. 즉, 올림을 의미합니다.

주차 요금을 나타내는 정수 배열 fees, 자동차의 입/출차 내역을 나타내는 문자열 배열 records가 매개변수로 주어집니다. 차량 번호가 작은 자동차부터 청구할 주차 요금을 차례대로 정수 배열에 담아서 return 하도록 solution 함수를 완성해주세요.

제한사항

- 문제를 확인해주세요

 

내가 푼 풀이

- Dictionary[String: [String]] 으로 해당하는 차량번호의 기록들 끼리 저장하고

- Dictionary[String: int] 로 해당 차량의 주차 이용시간들을 계산해서 정리한다.

- 정리된 주차이용시간들을 요금표로대로 계산하고 출력한다.

 

import Foundation

func solution(_ fees:[Int], _ records:[String]) -> [Int] {
    var dict = [String: [String]]()
    var resultDict = [String: Int]()
    var resultArr = [Int]()
    
    for i in records {
        var arr = i.split(separator: " ").map{String($0)}
        if dict[arr[1]] == nil {
            dict[arr[1]] = [arr[0], arr[2]]
        } else {
            dict[arr[1]]! += [arr[0], arr[2]]
        }
    }
    
    for i in dict {
        var arr = i.value
        var sum = 0
        for j in 0..<arr.count / 2 {
            var idx = j * 2
            var strArr = arr[idx].split(separator: ":").map{Int(String($0))!}
            var num = strArr[0] * 60 + strArr[1]
            if arr[idx+1] == "IN" {
                sum -= num
                if idx+2 == arr.count {
                    sum += 1439
                }
            } else {
                sum += num
            }
        }
        resultDict[i.key] = sum
        
    }
    
    for i in resultDict.sorted{$0.key < $1.key} {
        var sum = fees[1]
        if i.value <= fees[0] {
            resultArr.append(sum)
        } else {
            sum = sum + (Int(ceil(Double(i.value - fees[0]) / Double(fees[2]))) * fees[3])
            resultArr.append(sum)
        }
    }
    
    
    return resultArr
}

+ Recent posts