HIT해

[Swift/프로그래머스] 충돌위험 찾기 (완전탐색) 본문

Swift/Swift 알고리즘

[Swift/프로그래머스] 충돌위험 찾기 (완전탐색)

힛해 2024. 10. 31. 09:56
728x90

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

 

프로그래머스

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

programmers.co.kr

 

완전탐색 빡 구현 문제다.

 

코테랑 비슷한 수준의 구현을 요구해서 집중해서 풀어보았는데.

 

자료 구조를 얼마나 이해하고 있느냐가 중요했다.

 

 

처음에는 한 route의 이동경로를 각각의 배열에 담고

 

반복문을 통해서 비교를 하려 했지만.

 

고정된 크기의 route가 주어지는 것이 아니라 임의의 수를 가진 배열을 서로 비교해야한다 생각하니 앞길이 너무 막막했다.

 

var timeStampPostion = [Int : [String:[Int]]]()

 

 [시간 : [ 좌표 : [ 좌표에 있는 로봇들 ]]] 과 같은 형식으로 만들고

 

해당 시간의 values 를 순회해서 길이가 2이상인 값들을 return해준다.

 

풀이

import Foundation
func solution(_ points:[[Int]], _ routes:[[Int]]) -> Int {
    
    var pointCoordinates = [Int: (Int,Int)]()
    for (index,point) in points.enumerated(){
        pointCoordinates[index + 1] = (point[0],point[1])
    }
    
    var timePositions = [Int: [String:[Int]]]() // String이 포지션
    var maxTime = 0
    for (robotId, route) in routes.enumerated() {
        var positions = [(Int,Int)]()
        guard let startPoint = pointCoordinates[route[0]] else {continue}
        var currentR = startPoint.0
        var currentC = startPoint.1
        positions.append((currentR,currentC))
        
        // route 크기만큼 배열 순회하고자
        for i in 1..<route.count {
            guard let nextPoint = pointCoordinates[route[i]] else { continue }
            let nextR = nextPoint.0
            let nextC = nextPoint.1
            
            // Move in r direction
            while currentR != nextR {
                if currentR < nextR {
                    currentR += 1
                } else {
                    currentR -= 1
                }
                positions.append((currentR, currentC))
            }
            
            // Move in c direction
            while currentC != nextC {
                if currentC < nextC {
                    currentC += 1
                } else {
                    currentC -= 1
                }
                positions.append((currentR, currentC))
            }
            
        } // route내부 배열 순회
        
        var t = 0
        
        for (time , position) in positions.enumerated() {
            let positionKey = "\(position.0),\(position.1)"
             timePositions[time, default: [:]][positionKey, default: []].append(robotId)
            t = time
        }
        
        if t > maxTime {
            maxTime = t
        }
        
        
        
        
    } // routes 전체 배열 순회
   
    
    var result = 0

    for t in 0...maxTime {
        if let positions = timePositions[t] {
            for robotsAtPosition in positions.values {
                let k = robotsAtPosition.count
                if k >= 2 {
                    result += 1 
                }
            }
        }
    }

    return result
    
    }

 

 

let positionKey = "\(position.0),\(position.1)"
timePositions[time, default: [:]][positionKey, default: []].append(robotId)

 

튜플로 저장한 값을 String으로 변환해 키값으로 사용하고

 

딕셔너리의 default 구문을 활용해 빈값이라도 오류가 없도록 구현하였다.

 

딕셔너리를 잘 이해하고 있어야 풀 수 있는 문제같다.